Medidata’s business is enabling pharmaceutical and biotech companies to plan and execute their clinical trials with greater speed and efficiency, getting medicines approved and to patients faster. Part of that process involves collecting data from physicians but also increasingly from devices, from the patients themselves and from labs. The primary repository for this data is Rave, our Electronic Data Capture (EDC) system.

Rave has a set of web service API’s that enable data exchange using the Clinical Trial industry standard CDISC ODM - the Clinical Data Interchange Standards Consortium Operational Data Model.

The documentation for our Rave Web Service (RWS) API’s are available at

You can also learn about CDISC and the ODM at

Our Web Service API’s are RESTful - based on HTTP(S) authenticated using Basic Authentication (over HTTPS) or a form of HMAC Authentication called MAuth similar to the Amazon S3 REST authentication scheme.


Having a RESTful API make it easy to test things out with simple tools such as RESTClient but when you want to do more than view the data returned in a Browser you will need to turn to your programming language of choice and its HTTP libraries.

rwslib is a Python library based on Kenneth Reitz’s Requests designed to make it easier to work with the Rave Web Service API endpoints.

Installation is easy:

$ pip install rwslib

And it allows you to get started quickly:

>>> from rwslib import RWSConnection
>>> from rwslib.rws_requests import VersionRequest
>>> rws = RWSConnection('innovate')
>>> rws.send_request(VersionRequest())

The RWSConnection object manages the sending of request objects to the API endpoints. Each request has a return value based on the content of the response. In the above example the VersionRequest returns the RWS API version as a string but a request for a list of subjects would return a list of Subject objects, each with their own properties. But rwslib isn’t trying to hide its workings from you, all the HTTP status codes and headers are available via the last_result property of the connection:

>>> rws.last_result.url
>>> rws.last_result.status_code
>>> rws.last_result.headers['content-type']
text/plain; charset=utf-8
>>> rws.last_result.text

The library provides a full set of request objects that match the endpoints available via the API including helpers that allow you to post data in the ODM format into Rave:

>>> from rwslib import RWSConnection
>>> from rwslib.rws_requests import PostDataRequest
>>> r = RWSConnection('', 'username', 'password') #Authentication required for PostData
>>> data = """<?xml version="1.0" encoding="utf-8" ?>
... <ODM CreationDateTime="2013-06-17T17:03:29"
...      FileOID="3b9fea8b-e825-4e5f-bdc8-1464bdd7a664" FileType="Transactional"
...      ODMVersion="1.3" Originator="test system"
...      xmlns=""
...      xmlns:mdsol="">
...   <ClinicalData MetaDataVersionOID="1" StudyOID="Mediflex (DEV)">
...     <SubjectData SubjectKey="New Subject" TransactionType="Insert">
...       <SiteRef LocationOID="MDSOL" />
...       <StudyEventData StudyEventOID="SUBJECT">
...         <FormData FormOID="EN" FormRepeatKey="1" TransactionType="Update">
...           <ItemGroupData ItemGroupOID="EN" mdsol:Submission="SpecifiedItemsOnly">
...             <ItemData ItemOID="SUBJID" Value="1" />
...             <ItemData ItemOID="SUBJINIT" Value="AAA" />
...           </ItemGroupData>
...         </FormData>
...       </StudyEventData>
...     </SubjectData>
...   </ClinicalData>
... </ODM>"""
>>> resp = r.send_request(PostDataRequest(data))
>>> resp.istransactionsuccessful
>>> resp.fields_touched
>>> str(resp)
<Response ReferenceNumber="ebb3dfc7-fca6-4872-84b4-f0942cd66ce7"
          InboundODMFileOID="3b9fea8b-e825-4e5f-bdc8-1464bdd7a664" IsTransactionSuccessful="1"
          SuccessStatistics="Rave objects touched: Subjects=1; Folders=0; Forms=0; Fields=2; LogLines=0"

Creating ODM XML by hand can be error prone so rwslib provides a set of helpful builders to create valid ODM. The above ODM XML can be created using the Builder vocabulary:

>>> from import *
>>> odm = ODM("test system")(
...   ClinicalData("Mediflex","DEV")(
...      SubjectData("MDSOL","New Subject", "Insert")(
...         StudyEventData("Subject")(
...            FormData("EN", transaction_type="Update")(
...               ItemGroupData()(
...                  ItemData("SUBJINIT","AAA"),
...                  ItemData("SUBJID",001)
...               )
...            )
...         )
...      )
...   )
... )
>>> str(odm) #Returns the string representation of the odm object and all it's children.

Overall rwslib contains request objects that allow you to extract clinical data in ODM and CSV formats, download and upload study design metadata (forms, fields, codelist dictionaries etc) and to pull protocol deviations, comments and audit trail (historical data). We have used it to build systems that extract Protocol Deviations from Rave and transform them into a format that can be imported into Clinical Trial Management Systems, to upload data from wearable devices into Rave and to extract data for reporting.

Read the online documentation for rwslib.

We are making rwslib Open Source to encourage clients and third parties to build their own integrations with our systems. If you are not currently a client but are interested in working with Medidata’s API’s we have a developer program, it’s free to join. Please get in touch.