NAV
request response html javascript ruby

Prior Authorization API

Last updated: October 11, 2017

Published By:
CoverMyMeds, L.L.C.
Columbus, OH 43215
866-452-5017
www.covermymeds.com

Copyright © 2017 by CoverMyMeds, LLC.

Introduction

This API allows pharmaceutical clients to offer a compelling prior authorization solution to their customers. The API uses vanilla web services (REST), and is backed by development libraries that make using it a piece of cake.

After completing this integration, your ePA system will:

Workflow

Prior Authorization may be initiated “prospectively” in the doctor’s office, or “retrospectively” after a claim rejection in the pharmacy. The pharmacy industry generally favors moving toward prospective prior authorization, ideally at the point of prescribing. However, because the majority of PAs are initiated retrospectively today, we believe it is important to address both use cases.

The core workflow concept in the CoverMyMeds API is a “PA Task List” that is populated by both retrospective pharmacy (rejected claim) transactions and prospective physician (e-prescribing) transactions.

Integration Components

An integration with the CoverMyMeds API can be a quick process, with few components to implement in your system.

Webserver

You may run a webserver that allows us to POST changes to each existing PA, and to send new PAs that are initiated by integrated pharmacies. Updates to your existing PAs are provided by our callback service. The URL for your webserver is registered in your Developer Account. Using the Callback service is optional, but strongly suggested as it is the only way to receive prior authorizations from integrated pharmacies.

Token Management

You will store ids and tokens for each prior authorization. A detailed discussion of tokens is available below.

Mapping the Workflow to the API

Once created, PAs are worked in the system through the task list. You may keep your task list updated by storing PA data upon creation, and then updating it with the Callback service. Should you choose not to implement the Callback service, you may poll for updated PA information through the GET /requests/ or POST /requests/search/. In either case, you have full control over which users are allowed to access each PA request.

When a user clicks an item in your task list, you may choose to display the CoverMyMeds page for that PA within a frame in your system – with single-sign-on mediated by token-based access control – or you may use /request-pages for full control over look and feel of the request page.

Upon each change in status to a PA (e.g., health plan approval), CoverMyMeds’s Callback service will POST the request data to your server at the URL you have provided in your Developer Account.

Plans that participate in the ePA process with CoverMyMeds receive electronic PA requests, and provide electronic determinations (approved/denied) – sometimes in real-time.

Plans that do not participate in the ePA process receive a PA request via fax, on their appropriate drug-specific form. Determinations for such “classic” plans are provided directly to the prescriber (outside of the CoverMyMeds workflow), though approval or denial may be recorded directly by the user for posterity.

Quick Start

Use the included api_id and api_secret to play around, but get your own soon so that we can contact you if it looks like there is a problem. Sign up for instant access on the developer account page.

We will get started by using the API to create prior authorization (PA) requests and display a task list of PAs for your users.

Creating a PA

<!-- create a PA -->
<form method="post" action="https://api.covermymeds.com/requests" id="post_requests_quickstart">
  <label for="first_name">request[patient][first_name]</label>
  <input id="first_name" name="request[patient][first_name]" placeholder="(required)" type="text">
  <label for="last_name">request[patient][last_name]</label>
  <input id="last_name" name="request[patient][last_name]" placeholder="(required)" type="text">
  <label for="date_of_birth">request[patient][date_of_birth]</label>
  <input id="date_of_birth" name="request[patient][date_of_birth]" placeholder="(required)" type="text">
  <label for="state">request[state]</label>
  <input id="state" name="request[state]" placeholder="(required)" type="text" maxlength="2">
  <label for="drug_id">request[prescription][drug_id]</label>
  <input id="drug_id" name="request[prescription][drug_id]" value="094563" type="text">
  <input type="hidden" name="v" value="1">
  <input type="hidden" name="api_id" value="1vd9o4427lyi0ccb2uem">
  <input type="submit" value="Submit">
</form>

<!-- retrieve a PA -->
<form method="post" action="https://api.covermymeds.com/requests/search" id="post_requests_search_quickstart">
  <label for="requests_token_id">token_ids[]</label>
  <input id="requests_token_id" name="token_ids[]" placeholder="(required)" type="text">
  <input type="hidden" name="v" value="1">
  <input type="hidden" name="api_id" value="1vd9o4427lyi0ccb2uem">
  <input type="submit" value="Submit">
</form>
// Uncomment <script> tags if needed
// <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
// <script>
$(function () {
  // Create a PA
  $.ajax({
    method: 'post',
    url: 'https://api.covermymeds.com/requests',
    data: {
      api_id: '1vd9o4427lyi0ccb2uem',
      v: 1,
      request: {
        form_id: 'anthem_ppi',
        state: 'OH',
        patient: {
          first_name: 'Matt',
          last_name: 'Smith',
          date_of_birth: '01/27/1979'
        },
        prescription: {
          drug_id: '131079'
        }
      }
    },
    success: function (data) {
      console.log("Request created! " + JSON.stringify(data));
    }
  });

  // Retrieve a PA
  $.ajax({
    method: 'post',
    url: 'https://api.covermymeds.com/requests/search',
    data: {
      api_id: '1vd9o4427lyi0ccb2uem',
      v: 1,
      token_ids: ['gq9vmqai2mkwewv1y55x']
    },
    success: function (data) {
      console.log("Request search results: " + JSON.stringify(data));
    }
  });
});
// </script>

Create a PA by POSTing to /requests/. Use the code samples or the interactive documentation for the POST /requests resource.

The response includes an id and a tokens[id]. Save these and use them to retrieve the PA later.

Retrieving a PA

GET a PA using the /requests/ resource. You must authenticate your request with a token for the PA.

You can display the PA you created in the CoverMyMeds system by following the link in [requests][tokens][html_url], or you can build your own from a known token value by formatting it like this: https://www.covermymeds.com/request/view/{id}?token_id={access_token}&remote_user[display_name]={display_name}&remote_user[phone_number]={phone_number}&remote_user[fax_number]={fax_number}.

API Overview

REST

This is a REST API, which allows you to use any HTTP client you wish, including your favorite language’s HTTP library, curl, JavaScript, or HTML and a browser. In addition to system integrations, this documentation is built with the API, as are many components of our own website, and our sample EHR application.

The API is designed with intuitive resource-oriented URLs and HTTP response codes to indicate errors. We use built-in HTTP features like HTTP verbs.

Requests to the API are URL-encoded query or form data. This encoding will be handled automatically by most HTTP libraries. For example, jQuery’s AJAX methods take a JavaScript object, and automatically convert it to request data appropriately.

JSON is returned in all responses from the API, including errors.

Versioning

Currently, the API is on version “1”. Without changing the version number we may add additional fields to any response, accept additional fields on any resource. Your system should be written to tolerate these changes.

If we need to remove a field, change a data type, add an enumeration value, or move/rename a field we will increment the version number.

You must specify the version of the API you are using in all requests with the v attribute. Use the interactive documentation to see how this is done.

We will support API versions for at least one year from the next version’s release date. New versions will be announced with an email to the address registered with each Developer Account, and with personal follow-up from your Account Manager if we believe the version of the API you are using needs to be updated.

Development, Testing, and Staging

The base URI for the API is https://api.covermymeds.com. We encourage users to “play around” with our system. There is little you can do that will cause any real harm. Just remember that everything actually works. For example, when you send a fax, it will actually be transmitted. This is usually good, but remember to send faxes to yourself and not a provider or plan.

It is also possible to submit electronic transactions to health plans. To avoid this, you can take advantage of our test payer. You can interact with this payer like any other health plan, but without having to worry about starting a “real” PA. You can find out more about Mock in the Testing section.

CoverMyMeds also provides “always succeeds” and “always fails” fax numbers that you can use for testing:

614-999-9999 # faxes sent to this number will always succeed 614-555-5555 # faxes sent to this number will always fail

Interactive Documentation

The interactive documentation you see to the right of this section is built on our API. You can use the html tab to submit API requests using your browser.

We attempt to make all code, including the HTML forms copy/paste-able into your own file or console. If something doesn’t work after being directly copied, you may need to make a minor modification such as uncommenting a script tag-we try to mark these cases in comments in the code.

If you are having trouble getting something to run, contact us right away! Our job is to make this as easy as possible.

Library Code

You can use our jQuery plugins that allow you to easily build your integration in a browser or browser control in your desktop software.

Ruby

A rubygem is provided at rubygems.org.

Installation

Add this line to your application’s Gemfile:

# Gemfile gem 'covermymeds-api'

And then execute:

$ bundle

In order to use the gem, you’ll need to register to obtain an api key and secret. To learn more about using the rubygem, please consult the full documentation.

We can also provide bindings for other languages upon request.

Working with Requests

CoverMyMeds connects to dozens of health plans electronically, providing a “compatibility layer” for the provider in the case of plans that do not support electronic connection for ePA.

Creating a PA Request

You use the /requests resource to create a PA request. The API takes patient, prescription, prescriber, and payer information to create the request within the CoverMyMeds system as if it had been typed into the web site directly.

At a minimum, in the request, specify the patient’s first & last name, the patient’s state of residence, and the drug being prescribed. If you supply the patient’s insurance information (BIN, PCN, and GroupID), CoverMyMeds will automatically find the correct set of clinical questions from the payer. If not, the user will be prompted to select the appropriate payer the first time the request is accessed.

The drug may be specified with either the CoverMyMeds drug_id, obtained from a drug search or an NDC code. Most plans will approve requests at the “label name” (drug, strength, form) or an even higher level, so you may pick a “representative” NDC code when submitting your request.

Be sure to specify the patient’s state of residence, as opposed to the prescriber’s state or the state the patient works in. The “state” value is used for associating the patient to the correct payer, and finding the correct set of clinical questions.

Editing & Viewing Prior Authorization Requests

Supporting a great user experience across thousands of health plans’ distinct prior authorization forms, NCPDP ePA transactions, and proprietary integrations presents many user interface challenges.

A fundamental element of the PA request interface is the request page. The request page provides a user interface and workflow tools to allow the user to manage prior authorization requests. However, request pages offer different functionality depending on the form, the payer, and the drug, which makes it difficult to design UX that manages the workflow within your system.

CoverMyMeds offers two solutions to this problem. The first is to serve the prior authorization request page from the CoverMyMeds server embedded within your UI (for example, in an IFRAME), using the /request/view link described below. We encourage you to “theme” the page for your system. Details are included in the Theming section.

For custom integrations with a need to completely control the look and feel, or for desktop and mobile systems, we offer a workflow solution, which renders the pages in a workflow with user interface elements custom to your system, using the request-pages resource.

Choosing a PA item in your Task List should direct your user to the CoverMyMeds request page. CoverMyMeds provides a seamless transition with single-sign-on mediated by the access token and remote_user query string parameters.

You can get a URL to each PA request in [requests][tokens][html_url], or you can build your own from a known token value.

You format a link like this: https://www.covermymeds.com/request/view/{id}?token_id={access_token}&{remote_user}

Here is an actual link to a request.

Using remote_user

remote_user identifies the contact information for the client system’s user accessing the PA. Contact information is saved by CoverMyMeds in the PA’s history, as an audit trail. The remote_user parameter currently supports name, phone, and fax number. Additional values may be added over time.

Below is an example:

https://www.covermymeds.com/request/view/:id?token_id={access_token}&remote_user[display_name]={display_name}&remote_user[phone_number]={phone_number}&remote_user[fax_number]={fax_number}

Here is an actual link with remote user information.

Updating Data in a Request

The only PA request field available to update programmatically is the memo field. The memo field allows client systems to store up to 4000 bytes of client-system-specific information associated with a PA request, such as the database record ID of the patient record associated with the request. When supplied, the contents of the memo field are saved into the PA and returned upon each subsequent GET to /requests/{id}, exactly as they were supplied.

Deleting a Request

PA requests in the CoverMyMeds use a “soft-delete” approach in which PA requests are never really deleted, but rather the tokens associated with a request are deleted.

When a Request changes, the event history is updated and a Callback is enqueued for delivery to the client system.The events array is a time-stamped history of changes to the status of the Request.

When your system receives a callback with a DELETE event in the events array, you should remove the user’s token for the PA from the appropriate user’s task list. The remote_user object associated with the DELETE event contains a copy of the ?remote_user[] attributes that were presented when the user accesed the PA request on the CoverMyMeds portal, to help identify the user who wishes to delete the request.

Events

The events array is a time-stamped history of significant events in the lifecycle of a request. When a significant event occurs, the history is updated on the CoverMyMeds server and a callback is enqueued for delivery to the client system. The callback contains an array called “events”, with one entry for each event in the history of the PA. Events give client systems an audit trail for deletes and unrecoverable transmission failures. Using the event array, the client system can take appropriate action for the event, trigger workflow, and adjust the user’s view.

{
"events": [
    {
      "type":        "string (values: DELETE | REQUEST_FAX_FAILURE)",
      "time":        "ISO8601 datetime string",
      "remote_user": "object"
    }
  ]
}
Event Description
“DELETE” The request has been marked for deletion in the CoverMyMeds system. This can happen when the request is either deleted or archived by a user in the CoverMyMeds portal or through the API. Client systems should record the user who performed the deletion and delete local records of the PA appropriately. See Deleting a Request for more detail.
“REQUEST_FAX_FAILED” Occurs when the transmission to a fax-connected plan has suffered an unrecoverable failure. Faxes are retried several times to account for busy lines, phone system failure, or server errors. After the specified number of retries, the PA is marked as REQUEST_FAX_FAILED and a callback is sent to the client system which created the PA. Client systems must be written to tolerate such failures and allow user intervention to process the PA.

Changing the Theme

<div>
  <img alt="Brand Logo"
   src="http://www.mycompany.com/images/mylogo.png"
   />
</div>

<style type="text/css">
  #custom-theming {
    background-color: "black" !important;
  }
</style>

Client systems may specify the theming that is used on the CoverMyMeds request and related pages with “Custom Theming”, set in your Developer Account.

The theme text may contain HTML and inline CSS.

You may include a logo for your brand by base64 encoding it as a string and using it as an image source as shown to the right.

The theming data is not stored with each request. So remember that if you change it, requests that were created previously will reflect your new theme.

Disabling CoverMyMeds Functionality

<style type="text/css">
  .api-configurable.fax-control     { display: none !important; }
  .api-configurable.email-control   { display: none !important; }
  .api-configurable.delete-control  { display: none !important; }
</style>

You may wish to disable some functionality on the CoverMyMeds request page such as the “Fax” or “Delete” buttons. We provide documented css selectors that you can use in your custom theming for this purpose.

ui-hooks

The “First PA video” and “Chat with CoverMyMeds” sections can also be disabled on request.

Using Request Pages

As an alternative to framing the CoverMyMeds request pages within your UI, we offer a hypermedia API. Using the /request-pages resource, your system can natively follow the PA request workflow, without anticipating details.

The request-pages resource provides the data and actions appropriate to a PA workflow stage, independent of your UI technology, so that the user can work through the entire PA process within your system. Your system uses that information to draw UI for this stage in the workflow. The request-pages resource is designed for web-based, desktop, or mobile applications.

The Request-Pages Loop

To follow the workflow, your system works in a loop, rendering screens based on responses from the server. Each response presents the data and actions possible for the PA in its current state. Users traverse the workflow by invoking the actions returned with each response. The loop ends when the user no longer requests another link.

For each key in the forms property of the request-pages response:

  1. Record the form’s identifier property (e.g. pa_request); it will be used as a reference var form_identifier = request_page.forms.keys[0];
  2. When a question_id property is reached, retrieve its value from data[form_identifier]["some_question_id"], or the question_answer(s) property (if using typed-json)
  3. When a coded_reference property is reached, render the UI with coded reference data obtained by using the ref value in coded_references and performing an HTTP request to the specified endpoint
  4. Apply validations to the form field from the validations property
  5. Render links and submit buttons from the actions property. Executing an action will return another request-pages response to be rendered.

The data property

Example: "data": { "pa_request": { "patient_firstname": "Mark" "drug_name": "Ambien" "office_fax": null ... more fields ... } }

The “data” property holds the answers to the questions for each form or question set in the current PA request page. In the example above, pa_request is a hash of question_id’s and answers for each question in the pa_request form.

The question_sets property

"forms: { "string ref": { "question_sets": [ { "title": "string" "questions": [ { "question_type": "FREE_TEXT" "question_text": "string" "question_id": "string" "default_next_question_id": "string ref" "coded_reference": { "code": "string", "qualifier": "string", "code_system_version": "integer" "id": "string" "ref": "string ref" } flag: "REQUIRED" | "IMPORTANT" | null, "help_text": "string" } ] } ] } }

The question_sets property contains all of the display information required to render a set of questions in your system. For a web-based system, for example, a question set might render as a <fieldset> within a <form>, with the title property used as the <legend>. A question_set may contain one or more questions which correspond to one of several types of question possible.

Coded References

“Coded reference” is the use of an industry standard code system to describe patient information. request-pages supports the use of arbitrary vocabularies by payers in question sets. When a payer sends a coded reference for a question, it is included in the question as the coded_reference property.

The client system should use the coded_reference to retrieve the answer to the question, present it to the prescriber for their review or modification, and place it in the data or question_answer properties, depending on the Content-Type being used.

The provided_coded_references property

Provided coded references help client systems render user interface elements for specific questions. See request-pages for descriptions of provided coded references currently supplied by CoverMyMeds.

In the example below, the CoverMyMeds:form-search:1: coded reference returns a list of forms for a given drug, state, and plan.

"provided_coded_references": [ "CoverMyMeds:form-search:1:": { "href": "https://api.covermymeds.com/forms/?api_id=123ABC&v=1", "method": "GET", "data_fields": [ { "question_id": "form_id", "query_parameter": "q" }, { "question_id": "drug_DDID", "query_parameter": "drug_id" }, { "question_id": "state_id", "query_parameter": "state" } ] } ]

The data_fields array is used to construct a query string, using query_parameter as the key. The value is retrieved from the form field identified by the question_id key.

Each element in the data_fields array describes query string parameters for the URI in the href property. The question_id property gives the name of the element on the page with the value to supply. Put the value from the named element into the query string parameter named by the query_parameter property.

In this example, the full URL for the CoverMyMeds form search would be:

http://api.covermymeds.com/forms?api_id=123ABC&v=1&q=blue&drug_id=12345&state=OH

The validations property

"validations": { "icd9": { "type": "REGEX" "value": "^(V\d{2}(.\d{1,2})?|\d{3}(.\d{1,2})?|E\d{3}(.\d)?)$" "message": "Invalid icd9 code" "html_attributes": null } }

The validations property provides a set of client-side validations that should be applied to the rendered form to help the user complete the PA correctly. Validations are attached to a field by putting the name of the validation in the validations array for a question.

When the html_attributes property is present it provides a set of attributes that can applied to the rendered form to leverage a web browser’s built in validations.

See request-pages for details on these validation types.

The actions property

The actions property lets your system display the correct actions for a PA at any stage of its workflow, without knowing the full set of actions ahead of time. The workflow may vary by health plan and the type of connection (e.g., ePA, proprietary electronic connection, paper form).

The properties of an action give details on how to manipulate the PA for that workflow step.

Submitting each action requires the same authentication as GET /requests/{id}. See the authentication section for details.

"actions": [ { "ref": "pa_request" "title": "Save" "href": "http://www.covermymeds.com/request-pages/XXYYZZ?token_id=adfoi30238b012j" "method": "POST", "display": "DEFAULT" }, { "ref": null "title": "Email" "href": "http://www.covermymeds.com/request-pages/XXYYZZ/email?token_id=adfoi30238b012j" "method": "GET", "display": "DISABLED" }, { "ref": "pa_request" "title": "Send to Plan" "href": "http://www.covermymeds.com/request-pages/XXYYZZ/send_to_plan?token_id=adfoi30238b012j" "method": "POST", "display": "DEFAULT" } ]

Possible Form Elements

Each questions sub-property of the forms property will be rendered as a form element for the user to complete. The table below is a list of possible values for the question_type property:

question_type html corollary
FREE_TEXT <input type="text"/>
CHOICE <select><option></option></select>
DATE <input type="date"/>
NUMERIC <input type="number"/>
STATEMENT <div>
HIDDEN <input type="hidden"/>
FILE <input type="file"/>
CHECKBOX <input type="checkbox"/>
FREE_AREA <textarea/>

All of the questions share these properties:

Some of the question types modify the base question with extra or missing properties. See below for a table of properties and question types.

Property Data Type Description Question Type
question_id string unique identifier for the question within this question_set ALL
question_type string type of question. one of the values to the right ALL
question_text string the question being asked ALL
default_next_question_id string the next question to send the user to after this one is answered ALL
flag enum REQUIRED, IMPORTANT, or null. Hint for UI decoration. FREE_TEXT
CHOICE
DATE
NUMERIC
STATEMENT
FILE
CHECKBOX
FREE_AREA
help_text string String displayed to the user to help them answer the question. For example, “Enter a number between 1 and 10”. FREE_TEXT
CHOICE
DATE
NUMERIC
STATEMENT
FILE
CHECKBOX
FREE_AREA
coded_reference object A system-readable reference to the data being requested in the question for the EHR to supply automatically. FREE_TEXT
CHOICE
DATE
NUMERIC
STATEMENT
FILE
CHECKBOX
FREE_AREA
validations array array of strings referring to elements of the validations property. Validations are applied to the answer to the question. For example, this could point to a regular expression that validates a phone number. FREE_TEXT
CHOICE
NUMERIC
choices array In a CHOICE question, an array of objects representing the choices for the user. CHOICE
select_multiple boolean Indicates whether the user can select more than one choice or exactly one. CHOICE
comparisons array Array of numeric expressions for numeric questions to use for branching. NUMERIC
content_plain string Plain text of the statement. STATEMENT
content_html string HTML fragment representing the text of the statement. Allows formatting of text within the content. STATEMENT
checked_value string The value to submit to the EHR when this checkbox is selected. CHECKBOX
placeholder string Text to display in a FREE_TEXT or FREE_AREA as a prompt to the user. FREE_TEXT
FREE_AREA
question_answer string The answer to the question being asked. Only available in typed+json schema. FREE_TEXT
DATE
NUMERIC
HIDDEN FILE
CHECKBOX
FREE_AREA
question_answers* array The answers to a multiple-select choice question. Only available in typed+json schema. CHOICE (select_multiple:true)

Branching logic

The questions that are presented to the user may depend on their answer to previous questions. Both the NUMERIC and CHOICE question types can have properties that specify the branching logic.

The system may choose to show all the questions at once, or to step the user through one question at a time.

For CHOICE type questions

If not null the next_question_id property for the selected choice should be used to determine the next question to display.

If the next_question_id property is null, the default_next_question_id of the parent CHOICE should be the next question displayed.

For NUMERIC type questions

For NUMERIC type questions the comparisons array may include a list of conditions to select the next question. When next_question_id is null the default_next_question_id should be used.

"comparisons": [ { "type": "SINGLE_COMPARISON" "comparison_operator": "LT" "comparison_value": 5 "next_question_id": null } { "type": "RANGE_COMPARISON" "lower_bound_comparison_value": 5 "lower_bound_comparison_operator": "GT" "upper_bound_comparison_value": 10 "upper_bound_comparison_operator": "LE" "next_question_id": null } ]

STATEMENT type questions

Some forms need to display information only “questions” to the user. These “questions” do not get answers, they are simply displayed as static text.

"questions": [ { "question_type": "STATEMENT" "question_text": "" "content_plain": "This form was displayed because the search terms didn't match a specific Medicare plan or PBM." "content_html": "<p>This form was displayed because the <strong>search terms didn't match a specific Medicare plan or PBM.</strong></p>" "question_id": "reason_displayed" "default_next_question_id": "gender" "help_text": "" } ]

HIDDEN questions

Some forms require information supplied by the system, but not by the user. A HIDDEN question allows the system to send information to the payer, or to CoverMyMeds directly without involving the user.

"questions": [ { "question_type": "HIDDEN", "question_text": "we need some hidden information", "question_id": "hidden_question_1", "default_next_question_id": "reason_displayed", "flag": "IMPORTANT", "question_answer": "Jack Johnson" }

Error Handling in request-pages

Errors may be returned to the system while in its request-pages loop. For simplicity, we use standard HTTP status codes in responses as described in Handling Errors. Clients System implementations are expected to check the HTTP response codes before attempting to process the JSON response.

Callbacks

Callbacks are issued to a Client-System-specific endpoint with each status change to a request (e.g., health plan approval). Callbacks contain the latest known data for a request at the time of sending, formatted identically to the response schema in the requests resource. In this way, systems are guaranteed to receive the most up-to-date status of the request.

To simplify development, callbacks contain the latest known data for a request at the time of sending and a timestamped history of status changes. Client systems are guaranteed to receive callbacks with the most up-to-date status of the request.

While the CoverMyMeds system will make a best-effort to deliver callbacks in order for each change to the PA, due to the asynchronous nature of HTTP, it is possible that callbacks will arrive out of order or states will be skipped.

For example, you may receive a callback generated by the response from a payer before the one generated due to creation of your request.

Using Callbacks

To use the Callback service, implement an HTTP server to which CoverMyMeds may send data each time there is a status change, or when a new PA is created by an integrated pharmacy.

Register your endpoint as a global Callback URL in your Developer Account.

Changes to a request trigger asynchronous callbacks to your system. Your web service should return an HTTP status 200 or 201 when you receive the request and process it successfully, and an HTTP status of 500 otherwise. CoverMyMeds’ system will retry delivery of resolvable errors. CoverMyMeds will contact you directly if they are not successfully processed within a reasonable time-frame.

To prevent unwanted requests to your callback endpoint it’s common to apply HTTP Basic authentication. Our callback service supports HTTP Basic, by allowing username and password to be specified your callback URL.

https://username:password@your-server/pa-callbacks

Testing & Debugging

Before you have finished the implementation of your Callback Service, you may wish to use a service like RequestBin for your Callback URL to inspect the callback data.

You will see recent callbacks in your Developer Account. For example, you will be able to see that CoverMyMeds has delivered a Callback and what the HTTP Response code your server provided (if any), which should aid in debugging.

Callback Endpoint Security

You may choose to white-list the CoverMyMeds IP address range (ask CoverMyMeds support for details). Because your callback endpoint should not “give out” information, these security measures are highly recommended to avoid the potential misuse, but are not required.

Authentication

Registration

Visit the Developer Account page to register and manage your preferences.

When you register your system, you will be issued an api_id and an api_secret. These values will be used to log into your Developer Account in the future. Because we cannot send you your api_secret over email, and we cannot reset it without breaking your existing integration, there is no convenient method to offer a “password recovery” system. Guard your api_secret carefully.

You can also use your Developer Account to:

Only one developer account per email address is permitted. If the email address you wish to use is already in use, please contact us for assistance.

HTTP Header Based Authorization

For endpoints that require both your api_id and api_secret you can use conventional HTTP Basic authorization:

Authorization: Basic Base64Encode(<your-api_id>:<your-api_secret>)

For example, if your api_id is 123 and your api_secret is abc, your Authorization header value would be:

Basic MTIzOmFiYwo=

For endpoints that only require the token_id to access the PA request we use a variation on HTTP Bearer authorization:

Authorization: Bearer <your-api_id>+<your-token_id>

For example, with an api_id of 123 and a token_id of a1b2c3d4e5, your Authorization header value would be:

Bearer 123+a1b2c3d4e5

Authorization

Every API request requires the api_id for authentication of your requests. If the resource you are accessing could be destructive or involves PHI, additional authorization information is also required.

Authorization is provided by either the api_secret or request tokens. Tokens are used for all /requests/ methods that access existing PAs. The api_secret is used for methods that manage tokens.

CoverMyMeds uses tokens for accessing existing requests as a method of two-factor authentication. Using an API secret alone would expose a set of PA requests to potential compromise. A token for each PA request minimizes the chance that data from multiple PAs could be exposed in bulk. Tokens also can be securely used in a 100% client-side implementation.

Together, the api_secret and tokens are a compound password. Because the api_secret is used across your integration, it should never be exposed to your user. Exposing a token is less problematic because each token references only one PA request — which your user already has seen.

Token-Based Access Control

Many systems have the concept of a user. The user concept is frequently extended to include groups, organizations, and practice locations.

Together, these concepts are used to provision access to health records in your system. Within your system, the relationship between health records and users may be relatively simple, such as a foreign key in the record that points to a user, or it may be complex: managing a many-to-many relationship that includes the user’s department, role in the organization, and other hierarchies. Additional complexity is involved when one considers how user-level changes should modify record access over time. For example, if a new user is added to a record that was previously created, should this user now have access to the record?

The CoverMyMeds API is designed to avoid compromising your carefully designed access controls. By skipping the user concept entirely — using tokens that grant access to their associated PA - CoverMyMeds keeps your system in control of access to health information.

An initial token is created with each new PA through the POST /requests/ resource. The system may create destroy tokens with the /requests/tokens/ resource.

Each PA may have zero or more access tokens at any one time. If a PA does not have any access tokens, it is inaccessible through the API — effectively deleted. To undelete this PA, a new access token may be created.

Storing Tokens

Tokens should be stored by the system such that they can be used appropriately for any given user context. To take a simple example, imagine that your system has a single user access control scheme. The token management associated with this scheme would be easy—just keep a list of tokens with each user (perhaps all of the system-wide tokens in one table with a foreign key to the user).

Your system will probably be more complicated. You will want to provide access so that nursing and administrative staff can see prior authorizations for their doctors, and everyone can see the work in their workgroup.

The first two usage scenarios involve a user directly. The last usage scenario involves a prescriber that is associated with one or more users. For the first scenario, access tokens should be stored so that they may be retrieved by the other users that share work with the creating user. In the second and third scenario, access tokens should be stored so that they may be retrieved by all users that have access to the prescriber’s data.

Using Tokens

So that you may use client-side code to perform the integration, the /requests/ resource does not require use of the api_secret.

The POST method requires an api_id, but not the token_id because the user already has access to the information they are supplying. The PUT, GET, and DELETE methods require tokens because a user is retrieving or updating information they might not have supplied.

This means that access tokens are effectively passwords. Their security comes from being hard to guess (they are long random strings), and from not revealing them to users that should not be able to see their associated PA.

Each access token is unique for each request (i.e., they aren’t re-used). This makes their use lower risk than typical password-based authentication systems, which could provide access to large volumes of protected health information if they are compromised.

You may choose to actively manage tokens. This is unnecessary unless the tokens are compromised, but you may wish to consider it if you are using tokens in a client-side application. For example, you could regenerate tokens for a particular request if a user of the system shouldn’t have access to the PA request anymore. While low risk, it would be possible that this user had previously recorded the access token.

/requests/ Authentication & Authorization

method authentication
POST /requests/ api_id
only standard api_id authentication required, because we are creating a request that the user already has access to
GET /requests/ tokens
use a singular token_id
DELETE /requests/ tokens
POST /requests/search/ tokens
one or more token_ids
POST /requests/tokens/ api_secret
existing tokens aren’t a valid authentication mechanism to create new tokens for a request because tokens are their own resource
DELETE /requests/tokens/{id}/ api_secret
the api_secret ensures that users have access before deleting requests

Handling Errors

{
"errors":[
  {
  "code":401001,
  "message":"Unauthenticated: Please provide your api_id.",
  "debug":"An api_id is required, but no api_secret is required for this action."
  }]
}

It is important that your application handle errors responsibly. This generally means not failing silently, logging problems in your system, and showing good error messages to users.

Server Errors

To make handling errors as easy as possible, CoverMyMeds API uses real HTTP error codes, and returns a JSON object for each error. One or more errors may be returned. Each message should be displayed to the user, whereas debug information is for development staff.

It is possible, particularly when starting an integration project, that a request made to CoverMyMeds’ server will be so far from what is expected that the error message isn’t useful, or that you receive frequent 500 (Internal Server Errors). Please contact CoverMyMeds’ support to set up a live session with one of CoverMyMeds’ developers to watch your requests and help sort these problems out quickly.

Error Code Meaning
301 Moved permanently – the request-page is no longer found at this address (this error should be rare)
302 Found – you are being redirected because the operation completed and your response is coming from a new location
303 Found – same as a 302, but your system should switch the verb to “GET” when redirecting to the new URI
305 Use Proxy – repeat the request, using the proxy specified in the Location field of the response header
307 Temporary Redirect – the resource requested is temporarily available at a new location. system should re-issue to the new URI.
400 Bad Request
401 Unauthorized – The api_id and/or api_secret is missing or incorrect. See debug info in error message.
404 Not Found – The requested resource does not exist, or your request was missing required fields.
405 Method Not Allowed – You tried to access a resource with an unsupported method.
500 Internal Server Error – We had a problem processing your request. This may be a problem on our server, or it may be a badly formatted or incorrect request that we couldn’t process. Please contact us for help resolving this issue.
503 Service Unavailable – We’re temporarily offline for maintenance. Please try again later.

System Status

{
  "now":"1390452622",
  "status":"ok",
  "app_name":"requests_api",
  "version":"212aad2822869ff4fb88fac137224da991d485bb",
  "database":"true"
}

CoverMyMeds is fanatical about keeping our systems running, and you can expect API uptime to match or exceed the best “write-heavy” internet services (e.g., Gmail, Office 360, Salesforce, but not quite as high as Google Search). This means somewhere between three and four nines of availability.

Dashboard and Programmatic Monitoring

To promote transparency, we publish an Uptime Dashboard which shows realtime status information and historical uptime data.

You may also programmatically monitor each API resource by using its /_ping/ route. Should you wish to do this, the most important resource to monitor is https://api.covermymeds.com/requests/_ping. A status of ok indicates that systems are up. Anything else indicates a possible problem.

Testing the CoverMyMeds Integration

Setup

CoverMyMeds provides a test payer called Mock that you can send requests to and receive responses from. The test payer is configurable via the question sets it sends, and can be told exactly what status the response should have, so that you can test all use cases.

Pseudo Payer

When you are first starting your PA request, you will be asked for the patient, prescriber, patient’s state, medication, and the payer. These last three items – patient state, medication, and payer – are what are used to identify the questions sets you see and the payer who receives the request.

The mock payer (also called “Pseudo”) is referenced with the BIN, PCN, and Group numbers:

There are several forms associated with the mock payer, depending on the drug that is being prescribed:

Prescribed Drug Question Set/Form Returned
Spironolactone (NDC: 18837027430) Pseudo PBM 4-part
NEXium (NDC: 00186502031) CoverMyMeds Central Demo Form
Wellbutrin (NDC: 00173017855) Pseudo Classic Test Form (no ePA)

Interacting with the Mock payer

Every question set you receive from Mock will contain one or two “workflow” questions at the end. Generally, you will be asked whether you want a second round of questions, and/or what outcome you want for the request. Answering these questions is what notifies Mock of what kind of response to send back, so that you can control the expectations of any testing you do.

Workflows

There are a variety of workflows supported by CoverMyMeds, and each of them can be started using different state/medication/payer information.

Standard ePA workflow

STATE: either Massachusetts, Minnesota, New Jersey, Ohio, or Wisconsin MEDICATION: Spironolactone (NDC: 18837027430) PAYER: pseudo

Classic fax-based workflow

STATE: either Massachusetts, Minnesota, New Jersey, Ohio, or Wisconsin MEDICATION: Wellbutrin (NDC: 00173017855) PAYER: pseudo

Form with file attachments

STATE: either Massachusetts, Minnesota, New Jersey, Ohio, or Wisconsin MEDICATION: NEXium (NDC: 00186502031) PAYER: pseudo

Form with questions logic

STATE: either Massachusetts, Minnesota, New Jersey, Ohio, or Wisconsin MEDICATION: Suboxone 12-3MG films (NDC:12496121203) PAYER: us script

Test Plan

CoverMyMeds recommends passing the following tests before going live:

Test 1: Happy Path

Create a new PA Request for Spironolactone and the pseudo payer, and send it to the plan. You should receive back a question set.

Answer the questions however you wish, except for the two at the end: Second round of questions? No Determination? Approved

Send this request. You should receive back notification that your PA was completed favorably.

Test 2: Sad Path

Create a new PA Request for Spironolactone and the pseudo payer, and send it to the plan. You should receive back a question set.

Answer the questions however you wish, except for the two at the end: Second round of questions? No Determination? Denied

Send this request. You should receive back notification that your PA was completed unfavorably.

Test 3: Question Loop

Create a new PA Request for Spironolactone and the pseudo payer, and send it to the plan. You should receive back a question set.

Answer the questions however you wish, except for the two at the end: Second round of questions? Yes Determination? Random

Send this request. You should receive back a second question set.

Answer the new questions however you wish, including the determination question at the end.

Send this request. You should receive back notification that your PA was completed according to the determination you requested.

Test 4: Cancel a Request

Create a new PA Request for Spironolactone and the pseudo payer, and send it to the plan. You should receive back a question set.

Rather than answering the questions, try to cancel or delete your current PA. You should receive notification that your PA was successfully cancelled.

Test 5: Faxed PA

Create a new PA Request for Wellbutrin and the pseudo payer. You should see a question set.

Answer the questions however you like, and send to plan. When it asks you to enter a fax number, enter the auto-success number (614-999-9999). Verify it sent successfully. You will not get a determination back for this PA, since this request does not go to our test payer.

Test 6: File Attachments

Create a new PA Request for NEXium and the central payer. You should see a question set.

Answer the questions however you wish, except for the last two: Please include any additional information you feel is important to this request: The answer is not important, but underneath it are two file attachment fields. Select a file (PDF, JPG, PNG, or TIF) and attach it to this request. Select the Auto-Determination Scenario: Approved

Send this request. You should receive back notification that your PA was completed favorably.

Test 7: Ineligible for PA

Create a new PA Request for Spironolactone and the pseudo payer, but change the patient first name to ‘Invalid’. Send it to the plan. You should receive back notification that a PA is either not needed or not allowed.

Test 8: Question Logic (verifies proper rendering of the XML)

Create a new PA Request for Suboxone and the us script payer. You should see a question set.

Answer the questions however you wish and send the request. Verify it sent successfully. You will not get a determination back for this PA, since it does not go to our test payer.

Additional Tests

There are several other tests that will have to be run via the cURL command.

Send the following:

AUTH=`echo ":X" | uuencode -m _ | head -2 | tail -1` curl "https://api.covermymeds.com/forms?v=1" -X GET \ -H "Authorization: Basic $AUTH" \ -d "drug_id=094563" -d "state=OH" -d "q=caremark"

You should receive back JSON that includes multiple forms.

Invalid Plan (error case)

Send the following:

AUTH=`echo ":X" | uuencode -m _ | head -2 | tail -1` curl "https://api.covermymeds.com/forms?v=1" -X GET \ -H "Authorization: Basic $AUTH" \ -d "drug_id=094563" -d "state=OH" -d "q=00000"

You should receive back JSON that does not contain any forms.

Going Live

When the integration is nearing completion, we’ll assign an Account Manager to make sure you and your customers have direct access to our operations staff. Your Account Manager will provide:

Checklist

You’ll know you are ready to go live when you can complete our Go Live Checklist.

Item Complete? Note
Ability to create a PA Y / N
Task List with Filter/Sort/Search? Y / N
Callback System? Y / N Remember to update to your prod URL upon go-live
Errors handled properly? Y / N
Using own api_key and api_secret? Y / N Get new api_key and secret when you go to prod
Sending api_secret in auth header? Y / N
Discussed rollout plan with CoverMyMeds? Y / N We may disable API accounts that go into production without completing this step.
Provided CoverMyMeds with demo account to your system? Y / N This allows us to take screenprints for support staff
Exchanged support contacts with CoverMyMeds? Y / N
Executed mutual subcontract BAA? Y / N

Getting Help

1-866-452-5017
Mon - Friday: 8:00AM - 11:00PM EST
Saturday: 8:00AM - 3:00PM EST

It will greatly simplify your integration if you understand how the CoverMyMeds website system works, since you are reproducing its functionality in your application. You should create a CoverMyMeds account to explore how PAs work.

CoverMyMeds provides complete technical assistance during the integration. Questions may be sent to developers@covermymeds.com or to your dedicated support engineer. We can also arrange onsite integration sprints or remote pair programming with your developers. You may also call us for immediate help, although our general support staff are not always able to answer development-related questions.

We welcome your suggestions for improving the API. If you have a feature request or need to do something differently than how it is supported by the API, please get in touch and we can accommodate most requests.

HIPAA and Security

Overview

CoverMyMeds deploys a set of Policies and Procedures, together with Technical, Physical, and Administrative Safeguards to maintain compliance with the HIPAA Privacy Rule, Security Rule, Transactions and Code Sets Rule, and their implementing regulations.

For our users who are Covered Entities (e.g., providers, plans, or PBMs), CoverMyMeds functions as a Business Associate. In some situations, we may also function as a Health Care Clearinghouse (a type of Covered Entity). For example, we meet this definition when health care providers use a system that integrates with us, such as using this API, or when we communicate with the plan or PBM using the ePA standard.

CoverMyMeds also publishes a Privacy Policy and Terms of Service. These materials may be found in our online Privacy Center.

Because our service is used as part of a health care provider’s Treatment and Operations functions, and because we do not sell data or otherwise invoke the requirements, we are not generally required to obtain Patient Authorization or Consent.

Business Associate Agreement

CoverMyMeds uses a standard Business Associate Agreement with most providers, and may execute customized Business Associate Agreements with large health systems, pharmacies, and plans or PBMs (payers).

Integrating Systems will execute a Mutual Subcontract Business Associate Agreement with CoverMyMeds. This document obligates both parties to terms of the Business Associate Agreement, and allows data to be exchanged between the parties.

You may begin your integration without the final execution of the Mutual Subcontract Business Associate Agreement, but this agreement should be in place before any actual PHI is exchanged. In the interim, it is acceptable to use “mock” test data.

Controls and Security Assessments

Security and privacy compliance is a cornerstone of our business. We maintain an active internal program, and employ professional third-party auditors to evaluate our effectiveness.

Our programs have also been evaluated and assessed by many of the largest hospital systems, pharmacy chains, health plans and PBMs in the industry. We welcome our system partners to conduct their own assessment, including security audits, onsite site reviews, and other measures.

API Reference

Workflow Status

There are two types of requests managed by CoverMyMeds: true ePA and classic PA. True ePA requests are those which follow the workflow defined by the NCPDP SCRIPT specification, while classic PA requests are those with payers who have not yet adopted the standard.

While the API does its best to mask the distinction between ePA and classic PA, differences in the workflow are reflected in the workflow_status property. The is_epa flag on a request indicates which workflow applies. plan_outcome indicates the determination of the PA, when applicable.

ePA Workflow Status

Status Outcome Meaning
New null The PA has been created in CoverMyMeds, but not yet sent to the plan.
PA Request null A PA request was sent to the plan.
PA Response Favorable The PA was approved by the plan.
PA Response Unfavorable The PA was denied by the plan.
PA Response Pending The plan requires additional information in order to reach a determination.
Question Request null A PA initiation request was sent to the plan.
Question Response Favorable The plan approved the PA.
Question Response Unfavorable The plan denied the PA.
Question Response N/A The PA status is closed.
Appeal Request null An appeal request was sent to the plan.
Appeal Response Favorable The PA appeal has been approved by the plan.
Appeal Response Unfavorable The PA appeal has been denied by the plan.
Appeal Response Pending The plan requires additional information in order to reach a determination
Cancel Request Sent null A request to cancel the PA was sent, but the plan has not yet acknowledged the cancellation.
Provider Cancel Cancelled The plan acknowledged the cancellation of the PA request.
Archived Favorable The PA was approved by the plan and is now archived.
Archived Unfavorable The PA was denied by the plan and is now archived.
Archived Pending The plan requested additional information, but the PA was archived before a determination was reached.
Archived Cancelled The PA was cancelled and is now archived.
Archived Unknown No determination was made on the PA and the PA is now archived.
Expired null The question set has expired.
Failure null There was an unrecoverable failure in processing the ePA.

Classic PA Workflow Status

Status Outcome Meaning
New null The PA was created in CoverMyMeds, but not yet sent to the plan.
Shared null The PA was sent to another user.
Shared \ Accessed Online null The PA was viewed by the user it was shared with.
Sent to Plan null The PA was sent to the plan.
Archived Favorable The PA was approved by the plan.
Archived Unfavorable The PA was approved by the plan.
Archived Pending The plan requested additional information.
Archived Cancelled The PA was successfully canceled.
Archived Unknown No determination was made on the PA.
Appealed Favorable The PA was appealed by the user and approved by the plan.
Appealed Unfavorable The PA was appealed by the user and denied by the plan.
Appealed Pending The PA was appealed by the user, but the plan has requested more information.
Appealed Cancelled The user cancelled the appeal.
Appealed Unknown The user has created an appeal, but a determination has not been reached

Outcomes

Value Meaning
Favorable The PA was approved by the plan.
Unfavorable The PA was denied by the plan.
Cancelled The PA was successfully cancelled.
Pending The plan needs more information in order to make a determination.
Unknown No determination was made.
null The PA has yet to be sent to the plan, or is not in a state to have a valid outcome.

/requests/

The /requests/ resource is the workhorse of the API. It creates new prior authorizations (POST /requests/), retrieves a single PA (GET /requests/), and retrieves multiple PAs for use in your Task List or other bulk operations (POST /requests/search/).

For convenience, the HTTP response is the same across POST /requests/ and GET /requests/:id resources, and is the same form data that is used in the POST /requests/search resource and the Callback system. The GET /requests/:token_ids[] resources uses an abbreviated response format to allow for the speed required in a dashboard-style interface.

POST /requests/

<form method="post" action="https://api.covermymeds.com/requests?v=1" id="post_requests">
  <label for="requests_first_name">request[patient][first_name]</label>
  <input id="requests_first_name" name="request[patient][first_name]" placeholder="(required)" type="text">
  <label for="requests_last_name">request[patient][last_name]</label>
  <input id="requests_last_name" name="request[patient][last_name]" placeholder="(required)" type="text">
  <label for="requests_date_of_birth">request[patient][date_of_birth]</label>
  <input id="requests_date_of_birth" name="request[patient][date_of_birth]" placeholder="(required)" type="text">
  <label for="requests_state">request[state]</label>
  <input id="requests_state" name="request[state]" placeholder="(required)" type="text" maxlength="2">
  <label for="requests_drug_id">request[prescription][drug_id]</label>
  <input id="requests_drug_id" name="request[prescription][drug_id]" value="094563" type="text">
  <input type="hidden" name="api_id" value="1vd9o4427lyi0ccb2uem">
  <input type="submit" value="Submit">
</form>
// Uncomment <script> tags if needed
// <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
// <script>
$(function () {
  $.ajax({
    method: 'post',
    url: 'https://api.covermymeds.com/requests?v=1',
    data: {
      request: {
        form_id: 'anthem_ppi',
        state: 'OH',
        patient: {
          first_name: 'Matt',
          last_name: 'Smith',
          date_of_birth: '01/27/1979'
        },
        prescription: {
          drug_id: '131079'
        }
      }
    },
    beforeSend: function (xhr, settings) {
        if (!options.url) {
          xhr.setRequestHeader('Authorization',
            'Basic ' + Base64.encode('1vd9o4427lyi0ccb2uem' + ':x-no-pass'));
        }
    },
    success: function (data) {
      console.log("Request created! " + JSON.stringify(data));
    }
  });
});
// </script>
client = CoverMyApi::Client.new(your_api_id, your_api_secret)

new_request = client.request_data
new_request.patient.first_name = 'John'

request = client.create_request new_request
request.patient.first_name # => 'John'
POST /requests?v=1 HTTP/1.1
Host: api.covermymeds.com
Authorization: Bearer '{api_id}+x-no-pass'
Content-Type: application/json
{
  "request": {
    "urgent":   "boolean",
    "form_id":  "string",
    "state":    "required string",
    "memo":     "string",
    "patient": {
      "first_name":     "required string",
      "middle_name":    "string",
      "last_name":      "required string",
      "date_of_birth":  "required string",
      "gender":         "string",
      "email":          "string",
      "member_id":      "string",
      "phone_number":   "string",
      "address": {
        "street_1":  "string",
        "street_2":  "string",
        "city":      "string",
        "state":     "string",
        "zip":       "string"
      }
    },
    "payer": {
      "form_search_text":      "string",
      "bin":                   "string",
      "pcn":                   "string",
      "group_id":              "string",
      "medical_benefit_name":  "string",
      "drug_benefit_name":     "string"
    },
    "prescriber": {
      "npi":           "string",
      "first_name":    "string",
      "last_name":     "string",
      "clinic_name":   "string",
      "fax_number":    "string",
      "phone_number":  "string",
      "address": {
        "street_1":  "string",
        "street_2":  "string",
        "city":      "string",
        "state":     "string",
        "zip":       "string"
      }
    },
    "prescription": {
      "drug_id":                  "required string",
      "name":                     "string",
      "strength":                 "string",
      "frequency":                "string",
      "refills":                  "string",
      "dispense_as_written":      "string",
      "quantity":                 "string",
      "days_supply":              "string",
      "quantity_unit_of_measure": "string",
      "rationale":                "string"
    },
    "pharmacy": {
      "name":          "string",
      "fax_number":    "string",
      "phone_number":  "string",
      "address": {
        "street_1":  "string",
        "street_2":  "string",
        "city":      "string",
        "state":     "string",
        "zip":       "string"
      }
    },
    "enumerated_fields": {
      "icd9_0":        "string",
      "icd9_1":        "string",
      "icd9_2":        "string",
      "failed_med_0":  "string",
      "failed_med_1":  "string",
      "failed_med_2":  "string",
      "failed_med_3":  "string",
      "failed_med_4":  "string",
      "failed_med_5":  "string",
      "failed_med_6":  "string",
      "failed_med_7":  "string",
      "failed_med_8":  "string",
      "failed_med_9":  "string"
    }
  }
}
{
  "request": {
    "id":               "string",
    "api_id":           "string",
    "href":             "string",
    "html_url":         "string",
    "pdf_url":          "string",
    "thumbnail_urls":   ["string"],
    "workflow_status":  "string (values:  New, PA Request, PA Response, Provider Cancel, Question Request, Question Response, Appeal Request, Appeal Response, Failure, Expired, Archived, Shared, Cancel Request Sent, Shared \\ Accessed Online, Sent to Plan, Appealed)",
    "plan_outcome":     "string (values:  Favorable, Unfavorable, Cancelled, Pending, Unknown, Unsent, N/A)",
    "authorization_period": {
      "effective_date":   "ISO8601 datetime string",
      "expiration_date":  "ISO8601 datetime string"
    },
    "response_from_plan":    "string",
    "attachments_included":  "boolean",
    "is_epa":                "boolean",
    "is_appeal":             "boolean",
    "is_renewal":            "boolean",
    "urgent":                "boolean",
    "form_id":               "string",
    "state":                 "string",
    "memo":                  "string",
    "created_at":            "ISO8601 datetime string",
    "patient": {
      "first_name":     "string",
      "middle_name":    "string",
      "last_name":      "string",
      "date_of_birth":  "string",
      "gender":         "string",
      "email":          "string",
      "member_id":      "string",
      "phone_number":   "string",
      "address": {
        "street_1":  "string",
        "street_2":  "string",
        "city":      "string",
        "state":     "string",
        "zip":       "string"
      }
    },
    "payer": {
      "form_search_text":      "string",
      "bin":                   "string",
      "pcn":                   "string",
      "group_id":              "string",
      "medical_benefit_name":  "string",
      "drug_benefit_name":     "string"
    },
    "prescriber": {
      "npi":          "string",
      "first_name":   "string",
      "last_name":    "string",
      "clinic_name":  "string",
      "address": {
        "street_1":  "string",
        "street_2":  "string",
        "city":      "string",
        "state":     "string",
        "zip":       "string"
      },
      "fax_number":    "string",
      "phone_number":  "string"
    },
    "prescription": {
      "drug_id":                  "string",
      "name":                     "string",
      "strength":                 "string",
      "frequency":                "string",
      "refills":                  "string",
      "dispense_as_written":      "string",
      "quantity":                 "string",
      "days_supply":              "string",
      "quantity_unit_of_measure": "string",
      "rationale":                "string"
    },
    "pharmacy": {
      "name": "string",
      "address": {
        "street_1":  "string",
        "street_2":  "string",
        "city":      "string",
        "state":     "string",
        "zip":       "string"
      },
      "fax_number":    "string",
      "phone_number":  "string"
    },
    "enumerated_fields": {
      "icd9_0":        "string",
      "icd9_1":        "string",
      "icd9_2":        "string",
      "failed_med_0":  "string",
      "failed_med_1":  "string",
      "failed_med_2":  "string",
      "failed_med_3":  "string",
      "failed_med_4":  "string",
      "failed_med_5":  "string",
      "failed_med_6":  "string",
      "failed_med_7":  "string",
      "failed_med_8":  "string",
      "failed_med_9":  "string"
    },
    "tokens": [
      {
        "id":          "string",
        "request_id":  "string",
        "href":        "string",
        "html_url":    "string",
        "pdf_url":     "string"
      }
    ],
    "events": [
      {
        "type": "string: DELETE, REQUEST_FAX_FAILURE",
        "time": "ISO8601 datetime string",
        "remote_user": {
          "display_name": "string",
          "phone_number": "string",
          "fax_number": "string"
        }
      }
    ],
    "associated_requests": {
      "appeals": [
        {
          "id":   "string",
          "href": "url"
        }
      ],
      "renewals": [
        {
          "id":   "string",
          "href": "url"
        }
      ],
      "request_being_appealed": {
        "id":   "string",
        "href": "url"
      },
      "request_being_renewed":  {
        "id":   "string",
        "href": "url"
      }
    }
  }
}

Use the POST method to create a new prior authorization request. The HTTP response contains a link to the prior authorization and metadata about the request, including the new PA id and tokens, which should be saved in your system, and managed to provide appropriate access to the PA in the future. See the Authentication section for a detailed discussion. Click the buttons above to show the HTTP Request and Response schemas.

The response schema for this resource is identical to that of the GET /requests/ and POST /requests/search/ resources.

Workflow Considerations

A recommended workflow is to show the user the newly created request immediately after creating it, since that feature is likely to be used by an administrative staff person who wants to complete the PA in one sitting.

It is also recommended to provide users an overview of the prior authorization requests in a dashboard or task list. Keeping a cache of metadata for each request will ensure that the dashboard is quick to display. Update the metadata with each callback to make sure that your system displays the most relevant information.

GET /requests/{token_ids[]}

<form method="GET" action="https://api.covermymeds.com/requests/" id="get_requests_tokens">
  <label for="get_requests_tokens_token_id_1">token_id[]</label>
  <input id="get_requests_tokens_token_id_1" name="token_ids[]" type="text" value="gq9vmqai2mkwewv1y55x">
  <!-- Add as many additional IDs as you want -->
  <!-- <label for="post_requests_tokens_token_id_2">token_ids[]</label> -->
  <!-- <input id="post_requests_tokens_token_id_2" name="token_ids[]" placeholder="(required)" type="text"> -->
  <input type="hidden" name="v" value="1">
  <input type="hidden" name="api_id" value="1vd9o4427lyi0ccb2uem">
  <input type="submit" value="Submit">
</form>
// Uncomment <script> tags if needed
// <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
// <script>
$(function () {
  $.ajax({
    method: 'get',
    url: 'https://api.covermymeds.com/requests/',
    data: {
      api_id: '1vd9o4427lyi0ccb2uem',
      v: 1,
      token_ids: ['gq9vmqai2mkwewv1y55x']
    },
    success: function (data) {
      console.log("Request search results: " + JSON.stringify(data));
    }
  });
});
// </script>
GET /requests?v=1 HTTP/1.1
Host: api.covermymeds.com
Authorization: Bearer '{api_id}+x-no-pass'
Content-Type: application/json
{
  "token_ids": ["string", "string", ...]
}
{
  "requests": [
    "request":{
      "id":                   "string",
      "thumbnail_urls":       ["url"],
      "workflow_status":      "string (values: New, PA Request, PA Response, Provider Cancel, Question Request, Question Response, Appeal Request, Appeal Response, Failure, Expired, Archived, Shared, Cancel Request Sent, Shared \\ Accessed Online, Sent to Plan, Appealed)",
      "plan_outcome":         "string (values: Favorable, Unfavorable, Cancelled, Pending, Unknown, Unsent, N/A)",
      "is_epa":               "boolean",
      "state":                "string",
      "memo":                 "string",
      "created_at":           "ISO8601 datetime string",
      "patient": {
        "first_name":         "string",
        "last_name":          "string"
      },
      "prescriber": {
        "npi":                "string",
        "first_name":         "string",
        "last_name":          "string"
      },
      "prescription": {
        "name":               "string"
      },
      "tokens": [
        {
            "id":             "string",
            "request_id":     "string",
            "href":           "url",
            "html_url":       "url",
            "pdf_url":        "url",
            "thumbnail_url":  "url"
        }
      ]
    }
  ]
}

Use this method to return a list of prior authorizations to populate your dashboard, or similar other bulk request viewing.

Because this data is lightweight, filtering and pagination are not supported by the server resource. If you are implementing your own dashboard, it is important to provide search and filtering from your client application. Our dashboard JavaScript component can handle this for you.

GET /requests/{id}

<form method="get" action="https://api.covermymeds.com/requests/" id="get_requests">
  <label for="get_request_id">id</label>
  <input id="get_request_id" type="text" value="PF6FK9">
  <label for="get_request_token_id">token_id</label>
  <input id="get_request_token_id" name="token_id" type="text" value="gq9vmqai2mkwewv1y55x">
  <input type="hidden" name="v" value="1">
  <input type="hidden" name="api_id" value="1vd9o4427lyi0ccb2uem">
  <input type="submit" value="Submit">
</form>

<script>
  // The API URL requires a request ID in the URL, which is problematic in our
  // interactive documentation because the ID is a user-provided value.
  // This Javascript dynamically appends the request ID value to the form URL
  // when the form is submitted. You will likely not need this code in your
  // application.
  (function () {
    document.getElementById('get_requests').addEventListener('submit', function (event) {
      var form = event.target,
          token_id = document.getElementById('get_request_id').value;
          //Remove the last value before we put the new one on the URL
          form.action = form.action.substring(0, form.action.indexOf('/requests/')+"/requests/".length);
          // Append the token ID to the API URL
          form.action += token_id;
    }, true);
  }());
</script>
// Uncomment <script> tags if needed
// <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
// <script>
$(function () {
  var id = 'PF6FK9',
      token_id = 'gq9vmqai2mkwewv1y55x';

  $.ajax({
    method: 'get',
    url: 'https://api.covermymeds.com/requests/' + id,
    data: {
      token_id: token_id,
      v: 1,
      api_id: '1vd9o4427lyi0ccb2uem'
    },
    success: function (data) {
      console.log('Request results: ' + JSON.stringify(data));
    }
  });
});
// </script>
client = CoverMyApi::Client.new(your_api_id, your_api_secret)
# Get a single request
token_id = 'gq9vmqai2mkwewv1y55x'
request = client.get_request(token_id)

# Get many requests
other_token_id = 'Bg7vmqay2mkwewv1y33x'
requests = client.get_requests([token_id, other_token_id])
requests # => array of requests
GET /requests/{request_id}?v=1 HTTP/1.1
Host: api.covermymeds.com
Authorization: Bearer {api_id}+{token_id}
{
  "remote_user": {
    "display_name" : "string",
    "phone_number" : "string",
    "fax_number"   : "string"
  }
}

HTTP Response Schema

Use this method to retrieve information about a singular PA that already exists.

The response schema for this resource is identical to that of the POST /requests/ resource.

If you wish to display a returned PA to the user, you should display it on the CoverMyMeds website as described in the Using /requests section.

PUT /requests/{id}

<form method="put" action="https://api.covermymeds.com/requests/" id="put_requests">
  <label for="put_request_id">id</label>
  <input id="put_request_id" type="text" value="PF6FK9"/>
  <label for="put_request_token_id">token_id</label>
  <input id="put_request_token_id" type="text" name="token_id" value="gq9vmqai2mkwewv1y55x"/>
  <label for="put_request_memo">memo</label>
  <input id="put_request_memo" type="text" name="request[memo]" value="system-specific information"/>
  <input type="hidden" name="remote_user[display_name]" value="Jack B. Quick">
  <input type="hidden" name="remote_user[phone_number]" value="6145551212">
  <input type="hidden" name="v" value="1">
  <input type="hidden" name="api_id" value="1vd9o4427lyi0ccb2uem">
  <!-- This tells our server that we actually want this request to be put rather than POST -->
  <input type="hidden" name="_method" value="put">
  <input type="submit" value="Submit">
</form>

<script>
  // The API requires a token ID in the URL, which is problematic in our
  // interactive documentation because the ID is a user-provided value.
  // This Javascript dynamically appends the request ID value to the form URL
  // when the form is submitted. You will likely not need this code in your
  // application.
  (function () {
    document.getElementById('put_requests').addEventListener('submit', function (event) {
      var form = event.target,
          request_id = document.getElementById('put_request_id').value;
      // Append the token ID to the API URL if it's not there already
      if (form.action.indexOf(request_id) === -1) {
        form.action = 'https://api.covermymeds.com/requests/' + request_id;
      }
    }, true);
  }());
</script>
// Uncomment <script> tags if needed
// <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
// <script>
$(function () {
  var id = 'PF6FK9',
      token_id = 'gq9vmqai2mkwewv1y55x',
      remote_user = {
        "user": {
          "display_name":"Jack B Quick"
        }
      };

  $.ajax({
    method: 'put',
    url: 'https://api.covermymeds.com/requests/' + id,
    data: {
      token_id: token_id,
      remote_user: remote_user,
      v: 1,
      api_id: '1vd9o4427lyi0ccb2uem',
      request: {
        memo: "{\"data\":\"up to 4000 characters of system-specific information\"}"
      }
    },
    success: function (data) {
      console.log('Request results: ' + JSON.stringify(data));
    }
  });
});
// </script>
PUT /requests/{id}?v=1 HTTP/1.1
Host: api.covermymeds.com
Authorization: Bearer {api_id}+{token_id}
Content-Type: application/json
[HTTP Request Body](#post-requests)
204 No Content

Use the PUT method to update values of an existing PA request. All properties on the request are ignored except for the memo field, but CoverMyMeds reserves the right to change this in the future.

The schema for the body of the request is the same as POST /requests.

The memo field is a special field for client systems to store client-specific information associated with a PA request, such as the database record ID of the patient record associated with the request. When supplied, the contents of the memo field are saved into the PA and returned on each subsequent GET /requests/{id}. Up to 4000 bytes of information can be stored. The text will not be parsed or interpreted in any way on the CoverMyMeds server.

DELETE /requests/{id}

<form method="delete" action="https://api.covermymeds.com/requests/" id="delete_requests">
  <label for="delete_request_id">id</label>
  <input id="delete_request_id" type="text" value="PF6FK9"/>
  <label for="delete_request_token_id">token_id</label>
  <input id="delete_request_token_id" type="text" name="token_id" value="gq9vmqai2mkwewv1y55x"/>
  <label for="remote_user_username">remote_user[display_name]</label>
  <input id="remote_user_username" name="remote_user[display_name]" value="Jack B Quick" type="text"/>
  <label for="remote_user_phone">remote_user[phone_number]</label>
  <input id="remote_user_phone" name="remote_user[phone_number]" value="6145555555" type="text"/>
  <input type="hidden" name="v" value="1">
  <input type="hidden" name="api_id" value="1vd9o4427lyi0ccb2uem">
  <!-- This tells our server that we actually want this request to be DELETE rather than POST -->
  <input type="hidden" name="_method" value="delete">
  <input type="submit" value="Submit">
</form>

<script>
  // The API requires a token ID in the URL, which is problematic in our
  // interactive documentation because the ID is a user-provided value.
  // This Javascript dynamically appends the request ID value to the form URL
  // when the form is submitted. You will likely not need this code in your
  // application.
  (function () {
    document.getElementById('delete_requests').addEventListener('submit', function (event) {
      var form = event.target,
          request_id = document.getElementById('delete_request_id').value;
      // Append the token ID to the API URL if it's not there already
      if (form.action.indexOf(request_id) === -1) {
        form.action = 'https://api.covermymeds.com/requests/' + request_id;
      }
    }, true);
  }());
</script>
// Uncomment <script> tags if needed
// <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
// <script>
$(function () {
  var id = 'PF6FK9',
      token_id = 'gq9vmqai2mkwewv1y55x',
      remote_user = {
        "display_name":"Jack"
      };

  $.ajax({
    method: 'delete',
    url: 'https://api.covermymeds.com/requests/' + id,
    data: {
      token_id: token_id,
      remote_user: remote_user,
      v: 1,
      api_id: '1vd9o4427lyi0ccb2uem'
    },
    success: function (data) {
      console.log('Request results: ' + JSON.stringify(data));
    }
  });
});
// </script>
DELETE /requests/{id}?v=1 HTTP/1.1
Host: api.covermymeds.com
Authorization: Bearer {api_id}+{token_id}
Content-Type: application/json
{
  // at least 1 of the below attributes is required
  "remote_user": {
    "display_name" : "string",
    "phone_number" : "string",
    "fax_number"   : "string"
  },
  "token_id": "string"
}
204 No Content

Use this method to delete a request from the CoverMyMeds system. Deleting a request is different from deleting tokens: systems who created the request have access even without tokens. Once a request is deleted, however, it is removed from the system in a soft-delete, and all access is revoked.

POST /requests/search/

<form method="post" action="https://api.covermymeds.com/requests/search/" id="post_requests_search">
  <label for="post_requests_token_id_1">token_ids[]</label>
  <input id="post_requests_token_id_1" name="token_ids[]" type="text" value="gq9vmqai2mkwewv1y55x">
  <!-- Add as many additional IDs as you want -->
  <!-- <label for="post_requests_token_id_2">token_ids[]</label> -->
  <!-- <input id="post_requests_token_id_2" name="token_ids[]" placeholder="(required)" type="text"> -->
  <input type="hidden" name="v" value="1">
  <input type="hidden" name="api_id" value="1vd9o4427lyi0ccb2uem">
  <input type="submit" value="Submit">
</form>
// Uncomment <script> tags if needed
// <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
// <script>
$(function () {
  $.ajax({
    method: 'post',
    url: 'https://api.covermymeds.com/requests/search/',
    data: {
      api_id: '1vd9o4427lyi0ccb2uem',
      v: 1,
      token_ids: ['gq9vmqai2mkwewv1y55x']
    },
    success: function (data) {
      console.log("Request search results: " + JSON.stringify(data));
    }
  });
});
// </script>
client = CoverMyApi::Client.new(your_api_id, your_api_secret)
token_ids = ['gq9vmqai2mkwewv1y55x', 'bb8vmqai2mkwewv1y42y']
requests = client.get_requests(token_ids)
POST /requests/search?v=1 HTTP/1.1
Host: api.covermymeds.com
Authorization: Bearer '{api_id}+x-no-pass'
Content-Type: application/json
{
  "token_ids": ["string", "string", ...]
  // These are form data; for javascript, use an array such as:
  // token_ids: ["string", "string"]
}
{
  "requests": [
    // array of requests. each request schema is identical
    // to POST /requests HTTP response schema
  ]
}

Use this method to return a list of prior authorizations to populate your Task List, or to perform other bulk operations.

The response schema for the elements of the ‘requests’ array is identical to that of the POST /requests/ resource.

Filtering and pagination are not supported by the server resource. If you are implementing your own Task List, it is important to provide search and filtering from your client application. Our Task List JavaScript component can handle this for you.

/requests/tokens/

The /requests/tokens/ resource is provided for managing authentication tokens for each request. Note that tokens are an actual resource, not just an attribute of each request. This means they have their own API at /requests/tokens/ with verbs to provide CRUD services for them. This also means referring to requests in the /requests/tokens/ resource is different than you might otherwise expect. Here, a request id is called a request_id. Use the buttons to expose the request and response schemas to understand the naming convention.

POST /requests/tokens/

<form method="post" action="https://api.covermymeds.com/requests/tokens/" id="post_requests_tokens">
  <label for="token_id_1">request_ids[]</label>
  <input id="token_id_1" name="request_ids[]" placeholder="(required)" type="text">
  <input type="hidden" name="v" value="1">
  <input type="hidden" name="api_id" value="1vd9o4427lyi0ccb2uem">
  <input type="hidden" name="api_secret" value="q4trxd3rj8w38qfykqn-l9zcmxxlnibzwciof6pu">
  <input type="submit" value="Submit">
</form>
// Uncomment <script> tags if needed
// <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
// <script>
$(function () {
  $.ajax({
    method: 'post',
    url: 'https://api.covermymeds.com/requests/tokens',
    data: {
      request_ids: ['GA3MW8'],
      v: 1,
      api_id: '1vd9o4427lyi0ccb2uem',
      api_secret: 'q4trxd3rj8w38qfykqn-l9zcmxxlnibzwciof6pu'
    },
    success: function (data) {
      console.log('Token created! ' + JSON.stringify(data));
    }
  });
});
// </script>
client = CoverMyApi::Client.new(your_api_id, your_api_secret)
request_id = 'GA3MW8'
client.create_access_token(request_id)
POST /requests/tokens?v=1 HTTP/1.1
Host: api.covermymeds.com
Authorization: Basic Base64Encode({api_id}:{api_secret})
Content-Type: application/json
{
  "request_ids": ["string"]
  // This is a JSON array. For multiple, use:
  // request_ids: ["string", "string"]
}
{
  "tokens":  [
    {
      "id":                 "string",
      "request_id":         "string",
      "href":               "string",
      "html_url":           "string",
      "pdf_url":            "string"
    }
  ]
}

Each PA may have zero, one, or more tokens. Use this resource to create new tokens for a PA request. You may wish to create multiple tokens for a request so that you can assign a unique token for each user that will view a request, or to regenerate tokens if you believe they may have been compromised.

DELETE /requests/tokens/{id}/

<form method="post" action="https://api.covermymeds.com/requests/tokens/" id="delete_requests_tokens">
  <label for="delete_token_id">id</label>
  <input id="delete_token_id" name="id" placeholder="(required)" type="text">
  <input type="hidden" name="v" value="1">
  <input type="hidden" name="api_id" value="1vd9o4427lyi0ccb2uem">
  <input type="hidden" name="api_secret" value="q4trxd3rj8w38qfykqn-l9zcmxxlnibzwciof6pu">
  <!-- This tells our server that we actually want this request to be DELETE rather than POST -->
  <input type="hidden" name="_method" value="delete">
  <input type="submit" value="Submit">
</form>

<script>
  // The API URL requires a token ID in the URL,
  // which is problematic in our interactive documentation
  // because the ID is a user-provided value.
  // This Javascript dynamically appends the token
  // ID value to the form URL when the form is submitted.
  // You will likely not need this code in your application.
  (function () {
    document.getElementById('delete_requests_tokens').addEventListener('submit', function (event) {
      var form = event.target;

      // Append the token ID to the API URL
      form.action = "https://api.covermymeds.com/requests/tokens/"+document.getElementById('delete_token_id').value;
    }, true);
  }());
</script>
// Uncomment <script> tags if needed
// <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
// <script>
$(function () {
  var tokenId = 'eyu6thc8oy9upcop04k1';
  $.ajax({
    method: 'delete',
    url: 'https://api.covermymeds.com/requests/tokens/' + tokenId,
    data: {
      v: 1,
      api_id: '1vd9o4427lyi0ccb2uem',
      api_secret: 'q4trxd3rj8w38qfykqn-l9zcmxxlnibzwciof6pu'
    },
    success: function (data) {
      console.log('Token deleted successfully.');
    }
  });
});
// </script>
DELETE /requests/tokens/{token_id}?v=1 HTTP/1.1
Host: api.covermymeds.com
Authorization: Basic Base64Encode({api_id}:{api_secret})
204 No Content

Use this resource to delete tokens for a PA request. You may wish to do this if a user that has previously seen a request should no longer have access to it. A PA request is effectively deleted for your users when you remove all of the tokens to which it is associated.

/request-pages/

To use the request-pages resource:

  1. Create a new PA request with POST /requests/
  2. Using the tokens and id attributes from the response, make a GET request to request-pages/{id}
  3. If there is not an error in the response, render the request-pages response in the system (for example, in HTML), including the actions a user can take with the request.
  4. When users invoke an action, the server will return a new request-page. Loop back to step 3.

GET /request-pages/{id} (for web-based systems)

<form method="get" action="https://api.covermymeds.com/request-pages/" id="get_request_pages">
  <label for="get_request_pages_id">id</label>
  <input id="get_request_pages_id" type="text" value="PF6FK9">
  <label for="get_request_token_id">token_id</label>
  <input id="get_request_token_id" name="token_id" type="text" value="gq9vmqai2mkwewv1y55x">
  <input type="hidden" name="v" value="1">
  <input type="hidden" name="api_id" value="1vd9o4427lyi0ccb2uem">
  <input type="submit" value="Submit">
</form>

<script>
  // The API URL requires a request ID in the URL, which is problematic in our interactive documentation because the ID is a user-provided value. This Javascript dynamically appends the request ID value to the form URL when the form is submitted. You will likely not need this code in your application.
  (function () {
    document.getElementById('get_request_pages').addEventListener('submit', function (event) {
      var form = event.target,
          request_id = document.getElementById('get_request_pages_id').value;
          //Remove the last value before we put the new one on the URL
          form.action = form.action.substring(0, form.action.indexOf('/request-pages/')+"/request-pages/".length);
          // Append the PARequest ID to the API URL
          form.action += request_id;
    }, true);
  }());
</script>
// Uncomment <script> tags if needed
// <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
// <script>
$(function () {
  var id = 'PF6FK9',
      token_id = 'gq9vmqai2mkwewv1y55x';

  $.ajax({
    method: 'get',
    accepts: 'application/json'
    url: 'https://api.covermymeds.com/request-pages/' + id,
    data: {
      token_id: token_id,
      v: 1,
      api_id: '1vd9o4427lyi0ccb2uem'
    },
    success: function (data) {
      console.log('Request results: ' + JSON.stringify(data));
    }
  });
});
// </script>
client = CoverMyApi::Client.new(your_api_id, your_api_secret)

request_page = client.get_request_page('NT5HL9','nhe44fu4g22upqqgstea')
request_page.keys # => values corresponding to a request page

Or to save remote_user attributes to the request audit trail:
request_page = client.get_request_page('NT5HL9','nhe44fu4g22upqqgstea', { remote_user_key: 'remote_user_value' })
request_page.keys # => values corresponding to a request page
GET /request-pages/{id}?v=1 HTTP/1.1
Host: api.covermymeds.com
Authorization: Bearer '{api_id}+{token_id}'
Accept: application/json
{
  data: {
    pa_request: {
      // key:value pairs
      // "key" is the question_id from the corresponding question
      // "value" is the answer to the question
      // e.g. "patient_fname":"Jack"
    }
  },
  forms: {
    pa_request: {
      question_sets: [
        {
          "title": "string",
          questions: [
            // each element is one of the below
            {
              "question_type": "FREE_TEXT",
              "question_text": "string",
              "question_id": "string",
              "default_next_question_id": "string",
              "help_text": "string",
              "placeholder": "string",
              "flag": "REQUIRED" | "IMPORTANT" | null,
              "validations": ["string", ...],
              "coded_reference": {
                "code": "string",
                "qualifier": "string",
                "code_system_version": "string"
                "id": "string",
                "ref": "string"
              }
            },
            {
              "question_type": "CHOICE",
              "question_text": "string",
              "question_id": "string",
              "default_next_question_id": "string",
              "choices": [
                {
                  "choice_id": "string",
                  "choice_text": "string",
                  "additional_free_text_indicator": "string",
                  "next_question_id": "string"
                },
              ],
              "select_multiple": "boolean",
              "flag": "REQUIRED" | "IMPORTANT" | null,
              "help_text": "string",
              "validations": ["string", ...],
              "coded_reference": {
                "code": "string",
                "qualifier": "string",
                "code_system_version": "string"
                "id": "string",
                "ref": "string"
              }
            },
            {
              "question_type": "DATE",
              "question_text": "string",
              "question_id": "string",
              "default_next_question_id": "string",
              "flag": "REQUIRED" | "IMPORTANT" | null,
              "help_text": "string",
              "validations": ["string", ...],
              "coded_reference": {
                "code": "string",
                "qualifier": "string",
                "code_system_version": "string"
                "id": "string",
                "ref": "string"
              }
            },
            {
              "question_type": "NUMERIC",
              "question_text": "string",
              "question_id": "string",
              "default_next_question_id": "string",
              "flag": "REQUIRED" | "IMPORTANT" | null,
              "help_text": "string",
              "validations": ["string", ...],
              "coded_reference": {
                "code": "string",
                "qualifier": "string",
                "code_system_version": "string"
                "id": "string",
                "ref": "string"
              }
              "conditions": [
                {
                  "type": "SINGLE_COMPARISON",
                  "comparison_operator": "LT" | "GT" | "EQ"| "LE" | "GE",
                  "comparison_value": "integer",
                  "next_question_id": "string"
                },
                {
                  "type": "RANGE_COMPARISON",
                  "lower_bound_comparison_value": "integer",
                  "lower_bound_comparison_operator": "LT" | "GT" | "EQ" | "LE" | "GE",
                  "upper_bound_comparison_value": "integer",
                  "upper_bound_comparison_operator": "LT" | "GT" | "EQ" | "LE" | "GE",
                  "next_question_id": "string"
                }
              ]
            },
            {
              "question_type": "STATEMENT",
              "question_text": "string",
              "question_id": "string",
              "content_plain": "string",
              "content_html": "string",
              "help_text": "string",
              "default_next_question_id": "string",
              "coded_reference": {
                "code": "string",
                "qualifier": "string",
                "code_system_version": "integer",
                "id": "string",
                "ref": "string"
              },
            },
            {
              "question_type": "HIDDEN",
              "question_text": "string",
              "question_id": "string",
            },
            {
              "question_type": "FILE",
              "question_text": "string",
              "question_id": "string",
              "default_next_question_id": "string",
              "flag": "REQUIRED" | "IMPORTANT" | null,
              "help_text": "string",
              "validations": ["string", ...],
              "coded_reference": {
                "code": "string",
                "qualifier": "string",
                "code_system_version": "string"
                "id": "string",
                "ref": "string"
              }
            },
            {
              "question_type": "CHECKBOX",
              "question_text": "string",
              "question_id": "test_checkbox",
              "checked_value": "string",
              "default_next_question_id": "string",
              "flag": "REQUIRED" | "IMPORTANT" | null,
              "help_text": "string",
              "validations": ["string", ...],
              "coded_reference": {
                "code": "string",
                "qualifier": "string",
                "code_system_version": "string"
                "id": "string",
                "ref": "string"
              }
            },
            {
              "question_type": "FREE_AREA",
              "question_text": "string",
              "question_id": "string",
              "default_next_question_id": "string",
              "flag": "REQUIRED" | "IMPORTANT" | null,
              "help_text": "string",
              "placeholder": "string",
              "validations": ["string", ...],
              "coded_reference": {
                "code": "string",
                "qualifier": "string",
                "code_system_version": "string"
                "id": "string",
                "ref": "string"
              }
            }
          ]
        }
      ]
    }
  },
  "provided_coded_references": {
    "string (name of coded reference, e.g. 'ICD:9:1:')": {
      "href": "string",
      "method": "GET" | "POST",
      "data_fields": [
        {
          "question_id": "string",
          "query_parameter": "string"
        }
      ]
    },
    ...
  },
  "validations": {
    "string": { // id of validation
      "type": "REGEX | BYTE_LIMIT | MIME_TYPE",
      "value": "string",
      "message": "string",
      "html_attributes": "string"
    },
    ...
  },
  "actions": [
    {
      "ref": "string",
      "title": "string",
      "href": "string",
      "method": "string",
      "display": "DEFAULT | DISABLED"
    },
    ...
  ]
}

/request-pages/{id} is the starting point for a series of RESTful interactions in which each resource includes URLs for possible next states. Normal state transitions include things like "Save”, “Send to Plan” and “Archive,” but also exceptions like “Choose your form” (to handle user input to determine the correct PA recipient) and error handling actions.

Only the GET verb is provided for the /request-pages/ resource. There are no PUT, POST, or DELETE verbs for this resource – all data manipulation occurs through the HyperMedia interactions.

GET /request-pages/{id} (for client-server systems)

<form method="get" action="https://api.covermymeds.com/request-pages/" id="get_request_pages_cs">
  <label for="get_request_pages_cs_id">id</label>
  <input id="get_request_pages_cs_id" type="text" value="PF6FK9">
  <label for="get_request_token_cs_id">token_id</label>
  <input id="get_request_token_cs_id" name="token_id" type="text" value="gq9vmqai2mkwewv1y55x">
  <input type="hidden" name="v" value="1">
  <input type="hidden" name="api_id" value="1vd9o4427lyi0ccb2uem">
  <input type="submit" value="Submit">
</form>

<script>
  // The API URL requires a request ID in the URL, which is problematic in our interactive documentation because the ID is a user-provided value. This Javascript dynamically appends the request ID value to the form URL when the form is submitted. You will likely not need this code in your application.
  (function () {
    document.getElementById('get_request_pages_cs').addEventListener('submit', function (event) {
      var form = event.target,
          token_id = document.getElementById('get_request_pages_cs_id').value;

          //Remove the last value before we put the new one on the URL
          form.action = form.action.substring(0, form.action.indexOf('/request-pages/')+"/request-pages/".length);
          // Append the token ID to the API URL
          form.action += token_id + ".typed_json";
    }, true);
  }());
</script>
// Uncomment <script> tags if needed
// <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
// <script>
$(function () {
  var id = 'PF6FK9',
      token_id = 'gq9vmqai2mkwewv1y55x';

  $.ajax({
    method: 'get',
    accepts: 'application/typed+json',
    url: 'https://api.covermymeds.com/request-pages/' + id,
    data: {
      token_id: token_id,
      v: 1,
      api_id: '1vd9o4427lyi0ccb2uem'
    },
    success: function (data) {
      console.log('Request results: ' + JSON.stringify(data));
    }
  });
});
// </script>
GET /request-pages/{id}?v=1 HTTP/1.1
Host: api.covermymeds.com
Authorization: Bearer '{api_id}+{token_id}'
Accept: application/typed+json
{
  "request_page": {
    "forms": [{
        "identifier": "string",
        "question_sets": [{
            "title": "string",
            "questions": [
                {
                    "question_type": "FREE_TEXT",
                    "question_text": "string",
                    "question_id": "string",
                    "default_next_question_id": "string",
                    "help_text": "string",
                    "coded_reference": {
                        "code": "string",
                        "qualifier": "string",
                        "code_system_version": "string",
                        "id": "string",
                        "ref": "string"
                    },
                    "validations": ["string", ...],
                    "placeholder": "string",
                    "flag": "REQUIRED" | "IMPORTANT" | null,
                    "question_answer": "string"
                },
                {
                    "question_type": "CHOICE",
                    "question_text": "Gender",
                    "question_id": "gender",
                    "default_next_question_id": "prescribed_date",
                    "choices": [
                        {
                            "choice_id": "string",
                            "choice_text": "string",
                            "additional_free_text_indicator": "string",
                            "next_question_id": "string"
                        }
                    ],
                    "select_multiple": boolean,
                    "flag": "REQUIRED" | "IMPORTANT" | null,
                    "help_text": "string",
                    "validations": ["string", ...],
                    "question_answers": ["string", ...],
                    "coded_reference": {
                      "code": "string",
                      "qualifier": "string",
                      "code_system_version": "string"
                      "id": "string",
                      "ref": "string"
                    }
                },
                {
                    "question_type": "DATE",
                    "question_text": "string",
                    "question_id": "string",
                    "default_next_question_id": "string",
                    "flag": "REQUIRED" | "IMPORTANT" | null,
                    "help_text": "string",
                    "coded_reference": {
                      "code": "string",
                      "qualifier": "string",
                      "code_system_version": "string"
                      "id": "string",
                      "ref": "string"
                    },
                    "question_answer": "string" // ISO 8701 format
                },
                {
                    "question_type": "NUMERIC",
                    "question_text": "string",
                    "question_id": "string",
                    "default_next_question_id": "string",
                    "flag": "REQUIRED" | "IMPORTANT" | null,
                    "help_text": "string",
                    "validations": ["string", ...],
                    "coded_reference": {
                      "code": "string",
                      "qualifier": "string",
                      "code_system_version": "string"
                      "id": "string",
                      "ref": "string"
                    },
                    "comparisons": [
                        {
                            "type": "SINGLE_COMPARISON",
                            "comparison_operator": "LT" | "GT" | "EQ"| "LE" | "GE",
                            "comparison_value": integer,
                            "next_question_id": "string"
                        },
                        {
                            "type": "RANGE_COMPARISON",
                            "lower_bound_comparison_value": integer,
                            "lower_bound_comparison_operator": "LT" | "GT" | "EQ"| "LE" | "GE",
                            "upper_bound_comparison_value": integer,
                            "upper_bound_comparison_operator": "LT" | "GT" | "EQ"| "LE" | "GE",
                            "next_question_id": "string"
                        }
                    ],
                    "question_answer": integer
                },
                {
                    "question_type": "STATEMENT",
                    "question_text": "string",
                    "question_id": "string",
                    "content_plain": "string",
                    "content_html": "html_fragment_string",
                    "help_text": "string",
                    "flag": "REQUIRED" | "IMPORTANT" | null,
                    "question_answer": "string",
                    "coded_reference": {
                      "code": "string",
                      "qualifier": "string",
                      "code_system_version": "string"
                      "id": "string",
                      "ref": "string"
                    }
                },
                {
                    "question_type": "HIDDEN",
                    "question_text": "string",
                    "question_id": "string",
                    "default_next_question_id": "string",
                    "question_answer": "string"
                },
                {
                    "question_type": "FILE",
                    "question_text": "string",
                    "question_id": "string",
                    "default_next_question_id": "string",
                    "flag": "REQUIRED" | "IMPORTANT" | null,
                    "help_text": "string",
                    "question_answer": "string",
                    "coded_reference": {
                      "code": "string",
                      "qualifier": "string",
                      "code_system_version": "string"
                      "id": "string",
                      "ref": "string"
                    }
                },
                {
                    "question_type": "CHECKBOX",
                    "question_text": "string",
                    "question_id": "string",
                    "default_next_question_id": "string",
                    "flag": "REQUIRED" | "IMPORTANT" | null,
                    "help_text": "string",
                    "question_answer": "string",
                    "checked_value": "string",
                    "coded_reference": {
                      "code": "string",
                      "qualifier": "string",
                      "code_system_version": "string"
                      "id": "string",
                      "ref": "string"
                    }
                },
                {
                    "question_type": "FREE_AREA",
                    "question_text": "Explanation",
                    "question_id": "test_free_area",
                    "default_next_question_id": "string",
                    "coded_reference": {
                      "code": "string",
                      "qualifier": "string",
                      "code_system_version": "string"
                      "id": string
                      "ref": "string"
                    },
                    "flag": "REQUIRED" | "IMPORTANT" | null,
                    "help_text": "string",
                    "placeholder": "string",
                    "question_answer": "string"
                }
            ]
        }]
    }],
    "actions": [
        {
            "ref": "string",
            "title": "string",
            "href": "url_string",
            "method": "string",
            "display": "DEFAULT | DISABLED"
        },
    ],
    "provided_coded_references": [{
        "identifier": "string",
        "href": "url_string",
        "method": "string",
        "data_fields": [{
            "question_id": "string",
            "query_parameter": "string"
        }]
    }],
    "validations": [
        {
            "identifier": "string",
            "type": "REGEX | BYTE_LIMIT | MIME_TYPE",
            "value": "string",
            "message": "string (error message to show when validation fails)",
            "html_attributes": "string"
        },
    ]
}}

For client-server systems, typically written in a statically typed language like Java or C#, the schema is designed to conform to language data types. The same question types are represented, but the answers to each question are included within the question element, and property names are held static.

List of Provided Coded References

There are three coded reference vocabularies provided by CoverMyMeds: prior-auth-header, signature-pad, and form-search. Use of coded references within a client system is optional, but client systems must ignore coded reference types which they do not support. Provided coded references enhance the functionality of client systems when rendering request pages.

prior-auth-header

The prior-auth-header coded reference indicates a statement question that is to be used as the human-readable header for a request page. When this coded reference is used, the content_html and content_plain elements of the attached statement question will contain a description of the name, status, and drug used on the current PA request.

"coded_reference": { "qualifier": "CoverMyMeds", "code": "prior-auth-header", "ref": "CoverMyMeds:prior-auth-header:1:", "code_system_version": "1", "id": null }

Below is the schema of the content_html property. Client systems should style the content appropriately to match the look and feel of the system.

<table> <tbody> <tr> <td rowspan="3"> <img src="(link to thumbnail)"/> </td> <td>Status: (status of PA)</td> </tr> <tr> <td>Drug: (name and strength of drug)</td> </tr> <tr> <td>Form: (name of form)</td> </tr> </tbody> </table>

signature-pad

The signature pad reference indicates a question which captures a physician’s physical signature. See the demo app for a javascript implementation of a jquery widget supporting the signature-pad coded reference.

"coded_reference": { "qualifier": "CoverMyMeds", "code": "signature-pad", "code_system_version": "1", "id": null, "ref": "CoverMyMeds:signature-pad:1:" }

The data submitted to CoverMyMeds is a JSON array which describes pen strokes. Each element contains a flag indicating whether it is a new stroke, and the (x,y) coordinates of the pixel in the format: [[isNewStroke, x, y]], for example, [[1, 35, 100],[0,37,101],[0,38,102],[1,100,354]].

The form-search coded reference indicates that the question to which it is attached can use a type-ahead search of CoverMyMeds’ forms library. To use the form-search reference, supply the state, drug_id, and search terms to the URI referenced in the href parameter.

See The Provided Coded References Property for general use of provided coded references.

The query string parameter “q” will have the value supplied by the form_id element. The query string parameter drug_id will have the value of the question drug_DDID.

Client systems then parse the results of the form search to supply the answer to the question in the request-page.

"coded_reference": { "qualifier": "CoverMyMeds", "code": "form-search", "code_system_version": "1", "id": null, "ref": "CoverMyMeds:form-search:1:" }

"provided_coded_references": [ "CoverMyMeds:form-search:1:": { "href": "https://api.covermymeds.com/forms/?api_id={api_id}&v=1", "method": "GET", "data_fields": [ { "question_id": "form_id", "query_parameter": "q" }, { "question_id": "drug_DDID", "query_parameter": "drug_id" }, { "question_id": "state_id", "query_parameter": "state" } ] } ]

List of Validations

CoverMyMeds implements three validation types: REGEX, BYTE_LIMIT, and MIME_TYPES. REGEX can be used to apply a regular expression to a field so that it matches the proper format. BYTE_LIMIT and MIME_TYPES specify the maximum allowable size of a file and the acceptable file types, respectively, for file upload questions.

"validations": { "4eb6580445ed26024e6f3fb73e9ea597297bfe8b": { "type": "REGEX", "value": "^(0?[1-9]|1[012])/(0?[1-9]|[12][0-9]|3[01])/((19|20)\d\d)$", "message": null, "html_attributes": null }, "5240c74ad06c8227f9e48b519ce5f13a57fb842b": { "type": "REGEX", "value": "^([0-9]{3}-[0-9]{3}-[0-9]{4}( x[0-9]{1,5})?)?$", "message": null, "html_attributes": null }, "0cccb93cd37762b6ccee22fc655099592ce754dd": { "type": "REGEX", "value": "^\d{10}$", "message": null, "html_attributes": null }, "0a29765c2d77d2686fbdc2e79a270209d3f0641e": { "type": "REGEX", "value": "^[0-9]{3}-[0-9]{3}-[0-9]{4}( x[0-9]{1,5})?$", "message": null, "html_attributes": null }, "600a7ffe64bc6d088d473e785d8cc0f1930b125c": { "type": "REGEX", "value": "^\d*$"", "message": null, "html_attributes": null }, "8ebe39154b9e571facf10124f92972568f5735c5": { "type": "REGEX", "value": "^\d+$", "message": null, "html_attributes": null }, "b69d748f81bf59413e49efb78008e3dc18614eb7": { "type": "REGEX", "value": "^\d+$", "message": null, "html_attributes": null }, "f2f6cc605cfa7d9960ef1c2669c2a2dcd10fa114": { "type": "REGEX", "value": "^((0?[1-9]|1[012])/(0?[1-9]|[12][0-9]|3[01])/((19|20)\d\d))?$", "message": null, "html_attributes": null }, "27aa0b72bc0526aef046084100c80dfedbd06a11": { "type": "REGEX", "value": "\S+", "message": null, "html_attributes": null }, "016ad8f4b43d3939af2b6d57913a2f812f556206": { "type": "REGEX", "value": ""^[A-Z]{1}\d{5}$"", "message": null, "html_attributes": null }, "file_size": { "type": "BYTE_LIMIT", "value": 10485760, "message": "File size must be less than 10MB.", "html_attributes": null }, "file_type": { "type": "MIME_TYPES", "value": [ "image/jpeg", "image/tiff", "image/png", "application/pdf" ], "message": "Allowed types: .pdf, .jpg, .png, or .tif", "html_attributes": null } }

The REGEX validations are described in the table below.

id type regex message
600a7ffe64bc6d088d473e785d8cc0f1930b125c integer ^\d*$“ Whole number. Example: 1
8ebe39154b9e571facf10124f92972568f5735c5 integer required ”^\d+$“ Whole number. Example: 1 (required)
b69d748f81bf59413e49efb78008e3dc18614eb7 number required ”^[-+]?([0-9]+(.[0-9]+)?|.[0-9]+)$“ Decimal number. Example 1.0 (required)
f2f6cc605cfa7d9960ef1c2669c2a2dcd10fa114 date ^((0?[1-9]|1[012])/(0?[1-9]|[12][0-9]|3[01])/((19|20)\d\d))?$ Date. Example: (mask)
4eb6580445ed26024e6f3fb73e9ea597297bfe8b date required ^(0?[1-9]|1[012])/(0?[1-9]|[12][0-9]&#124;3[01])/((19|20)\d\d)$ Date. Example: (mask) (required)
5240c74ad06c8227f9e48b519ce5f13a57fb842b phone ^([0-9]{3}-[0-9]{3}-[0-9]{4}( x[0-9]{1,5})?)?$ US phone number. Example: (999-999-9999)
0a29765c2d77d2686fbdc2e79a270209d3f0641e phone required ^[0-9]{3}-[0-9]{3}-[0-9]{4}( x[0-9]{1,5})?$ US Phone number. Example (mask) (required)
0cccb93cd37762b6ccee22fc655099592ce754dd NPI ^\d{10}$ 10-digit NPI
27aa0b72bc0526aef046084100c80dfedbd06a11 alphanumeric, required, non-spaces \S+ Text (no spaces). Example: John
016ad8f4b43d3939af2b6d57913a2f812f556206 UPIN ”^[A-Z]{1}\d{5}$“ Unique Physician Identification Number. Example A12345.

/forms/

GET /forms/

<form method="get" action="https://api.covermymeds.com/forms" id="get_forms">
  <label for="forms_query">q</label>
  <input id="forms_query" name="q" placeholder="(required)" type="text">
  <label for="forms_bin">bin</label>
  <input id="forms_bin" name="bin" placeholder="(required)" type="text">
  <label for="forms_pcn">pcn</label>
  <input id="forms_pcn" name="pcn" placeholder="(required)" type="text">
  <label for="forms_group_id">group_id</label>
  <input id="forms_group_id" name="group_id" placeholder="(required)" type="text">
  <label for="forms_drug_id">drug_id</label>
  <input id="forms_drug_id" name="drug_id" type="text" value="143562">
  <label for="forms_state">state</label>
  <input id="forms_state" name="state" placeholder="(required)" type="text" maxlength="2">
  <input type="hidden" name="v" value="1">
  <input type="hidden" name="api_id" value="1vd9o4427lyi0ccb2uem">
  <input type="submit" value="Submit">
</form>
// Uncomment <script> tags if needed
// <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
// <script>
$(function () {
  $.ajax({
    method: 'get',
    url: 'https://api.covermymeds.com/forms',
    data: {
      q: 'bcbs',
      state: 'OH',
      drug_id: '064691',
      v: 1,
      api_id: '1vd9o4427lyi0ccb2uem'
    },
    success: function (data) {
      console.log('Form search results: ' + JSON.stringify(data));
    }
  });
});
// </script>
client = CoverMyApi::Client.new(your_api_id, your_api_secret)
search_term = 'bcbs'
drug_id = '064691'
state = 'OH'

forms = client.form_search(search_term, drug_id, state)
forms.first.form_id # 'medco_general_pa_form_21039'
GET /forms?v=1&drug_id={drug_id}&state={state_abbreviation}&q={search+terms} HTTP/1.1
Host: api.covermymeds.com
Authorization: Bearer '{api_id}+x-no-pass'

# You can also specify the bin, pcn, and group id.
GET /forms?v=1&drug_id={drug_id}&state={state}&bin={bin}&pcn={pcn}&group_id={rxgroup}&threshold={number}
Host: api.covermymeds.com
Authorization: Bearer '{api_id}+x-no-pass'
{
  "forms": [{
      "id": number,
      "href": "url",
      "name": "string",
      "description": "string",
      "directions": "string",
      "request_form_id": "string",
      "thumbnail_url": "url",
      "is_epa": "boolean",
      "contact_name": "string",
      "contact_phone": "string",
      "contact_fax": "string",
      "score": decimal number
    }
  ]
}

When you create a new PA through the POST /requests/ resource, you may specify the form_id, or you may leave it blank so that the user may pick the form through CoverMyMeds’s form search dialog, presented when the user first visits the PA request.

The GET /forms/ resource allows you to implement a form search so the user may pick the appropriate prior authorization “form” for their request, allowing the system to specify a form_id when creating a request. The /forms/ resource works with both “paper” forms, and electronic prior authorization (ePA) requests.

The GET method takes these parameters:

The general “q” form search identifies matches based on the drug, the state, and a text query. The text query is processed against our data for plan names, PBM names, form names, BIN, PCN, Group ID, and CMS Contract IDs. The result is a “scored” list of the most appropriate forms for the request. The top result is the best match based on the criteria.

If the bin, pcn, or group_id parameters are present, the /forms resource performs a structured search. In general, if your client system knows the BIN, PCN, and RxGroup of the patient, the structured search will give much more accurate results. If the search terms are sparse or free-text, then the general “q” search will provide more accurate results.

As a rule of thumb, it is best to include the form search as part of interactions that are conducted by administrative staff, such as the New PA Form, and to skip the search during the e-prescribing workflow.

We publish a jQuery plugin that allows you to implement a type-ahead search with very little effort.

GET /forms/{id}

<form method="get" action="https://api.covermymeds.com/forms/" id="get_form">
  <label for="get_form_id">id</label>
  <input id="get_form_id" placeholder="(required)" type="text" value="medco_general_pa_form_21039">
  <input type="hidden" name="v" value="1">
  <input type="hidden" name="api_id" value="1vd9o4427lyi0ccb2uem">
  <input type="submit" value="Submit">
</form>

<script>
  // The API URL requires a request ID in the URL, which is problematic in our interactive documentation because the ID is a user-provided value. This Javascript dynamically appends the request ID value to the form URL when the form is submitted.  You will likely not need this code in your application.
  (function () {
    document.getElementById('get_form').addEventListener('submit', function (event) {
      var form = event.target,
          id = document.getElementById('get_form_id').value;
          //Remove the last value before we put the new one on the URL
          form.action = form.action.substring(0, form.action.indexOf('/forms/')+"/forms/".length);
          // Append the form ID to the API URL
          form.action += id;
    }, true);
  }());
</script>
// Uncomment <script> tags if needed
// <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
// <script>
$(function () {
  $.ajax({
    method: 'get',
    url: 'https://api.covermymeds.com/forms',
    data: {
      id: 'medco_general_pa_form_21039',
      v: 1,
      api_id: '1vd9o4427lyi0ccb2uem'
    },
    success: function (data) {
      console.log('Form search results: ' + JSON.stringify(data));
    }
  });
});
// </script>
client = CoverMyApi::Client.new(your_api_id, your_api_secret)
form_id = 'medco_general_pa_form_21039'

form = client.get_form(form_id)
form.name # Form Name
GET /forms/{id}?v=1 HTTP/1.1
Host: api.covermymeds.com
Authorization: Bearer '{api_id}+x-no-pass'
{
  "form": {
    "id": "integer",
    "href": "string",
    "name": "string",
    "description": "string",
    "directions": "string",
    "request_form_id": "string",
    "thumbnail_url": "string",
    "is_epa": "boolean",
    "contact_name": "string",
    "contact_phone": "string",
    "contact_fax": "string"
  }
}

The GET /forms/ resource retrieves detailed information about a specific form, including the payer contact information, whether or not it is an ePA form, and a long-text description of the form.

/drugs/

GET /drugs/

<form method="get" action="https://api.covermymeds.com/drugs" id="get_drugs">
  <label for="drugs_query">q</label>
  <input id="drugs_query" name="q" placeholder="(required)" type="text">
  <input type="hidden" name="v" value="1">
  <input type="hidden" name="api_id" value="1vd9o4427lyi0ccb2uem">
  <input type="submit" value="Submit">
</form>
// Uncomment <script> tags if needed
// <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
// <script>
$(function () {
  $.ajax({
    method: 'get',
    url: 'https://api.covermymeds.com/drugs',
    data: {
      q: 'xanax',
      v: 1,
      api_id: '1vd9o4427lyi0ccb2uem'
    },
    success: function (data) {
      console.log('Drug search results: ' + JSON.stringify(data));
    }
  });
});
// </script>
client = CoverMyApi::Client.new(your_api_id, your_api_secret)
search_term = 'xanax'

drugs = client.drug_search(search_term)
drugs.first.name # 'Xanax'
GET /drugs?v=1&q={search+terms} HTTP/1.1
Host: api.covermymeds.com
Authorization: Bearer '{api_id}+x-no-pass'
{
  "drugs": [
    {
      "id":                        "integer",
      "href":                      "string",
      "gpi":                       "string",
      "name":                      "string",
      "strength":                  "string",
      "strength_unit_of_measure":  "string",
      "route_of_administration":   "string",
      "dosage_form":               "string",
      "full_name":                 "string"
    }
  ]
}

You must specify the request[prescription][drug_id] when a new PA is created through the POST /requests/ resource. Optionally, you may also include quantity and days supply, values which are usually required in the prior authorization submission to the plan.

The GET /drugs/ resource allows you to implement a drug search so the user can pick a drug for their request. When a drug is picked, you get our internal drug id. Partial and full drug names are supported. For example, click here for a search for “Nex”.

You can use the /drugs/ resource to implement a “type-ahead” search. We publish a jQuery plugin that allows you to do this with very little effort.

GET /drugs/{drug_id}

<form method="get" action="https://api.covermymeds.com/drugs" id="get_drug">
  <label for='get_drug_id'>NDC or CoverMyMeds Drug Number</label>
  <input type="text" id="get_drug_id" name="drug_number" value=""/>
  <input type="hidden" name="v" value="1"/>
  <input type="hidden" name="api_id" value="1vd9o4427lyi0ccb2uem"/>
  <input type="submit" value="Submit"/>
</form>

<script>
  // The API URL requires a drug ID, which is problematic in our interactive documentation because the ID is a user-provided value. This Javascript dynamically appends the drug ID value to the form URL when the form is submitted. You will likely not need this code in your application.
  (function () {
    document.getElementById('get_drug').addEventListener('submit', function (event) {
      var form = event.target,
          drug_id = document.getElementById('get_drug_id').value;

      // reset form for when this is submitted multiple times
      form.action = "https://api.covermymeds.com/drugs";

      // Append the token ID to the API URL if it's not there already
      if (form.action.indexOf(drug_id) === -1) {
        form.action += "/" + drug_id;
      }
    }, true);
  }());
</script>

// Uncomment <script> tags if needed
// <script src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
// <script>
$(function () {
  var drug_id = document.getElementById('get_drug_id').value;
  $.ajax({
    method: 'get',
    url: 'https://api.covermymeds.com/drugs/'+drug_id,
    data: {
      v: 1,
      api_id: '1vd9o4427lyi0ccb2uem'
    },
    success: function (data) {
      console.log('Drug search results: ' + JSON.stringify(data));
    }
  });
});
// </script>
client = CoverMyApi::Client.new(your_api_id, your_api_secret)
drug_id = 123

drug = client.get_drug(drug_id)
drug.name # Xanax
GET /drugs/{drug_id}/?v=1 HTTP/1.1
Host: api.covermymeds.com
Authorization: Bearer '{api_id}+x-no-pass'
{
  "drug": {
    "id": "string (Medispan ID)",
    "gpi": "string",
    "sort_group": string,
    "sort_order": string,
    "name": "string",
    "route_of_administration": "string",
    "dosage_form": "string",
    "strength": "string",
    "strength_unit_of_measure": "string",
    "full_name": "string",
    "href": "string",
    "representative_ndc": "ndc_code"
  }
}

This API allows a system to get information about a particular drug in the CoverMyMeds database, including the internal CoverMyMeds code or the NDC code for that drug.

drug_id may be an NDC code (9 or 11 digit), or CoverMyMeds’s internal drug_id returned from the GET /drugs/ resource. Submitting an NDC is really just syntactic sugar — we will convert the NDC code you submitted to our internal identifier when we create the request.

Submitting an NDC code is advantageous when you are initiating the request from the e-prescribing workflow where the user has already “picked” a drug in your system, and you know the NDC code. The /drugs/ resource is a good way to show a type-ahead search, such as you will need in the New PA form, so using CoverMyMeds’s internal drug_id can be convenient here.