Every API here is available over the APIs.io API and to AI agents over MCP.
{
"openapi": "3.1.0",
"info": {
"contact": {
"url": "https://support.collaborativedrug.com/hc/en-us/requests/new"
},
"description": "Collaborative Drug Discovery provides an API (Application Programming\nInterface) that can be used for secure programmatic access to your vault\ndata. Using the API, client applications such as Microsoft Office, Pipeline\nPilot, Knime and others can be configured to directly access and process\nchemical and biological data from CDD Vault.\n\n**Download the full specification:** [OpenAPI YAML](cdd_openapi.yaml) ·\n[OpenAPI JSON](cdd_openapi.json). Import it into Postman, an SDK/client\ngenerator, or your IDE.\n\n\n**For LLMs / AI tools:** [llms.txt](llms.txt) (concise index) ·\n[llms-full.txt](llms-full.txt) (full documentation text).\n\n## Using the API\n\nThe API is designed using RESTful principles: objects (resources) are\nidentified by URLs, and actions are specified by HTTP verbs. (If that doesn't\nmean anything to you, don't worry — it isn't necessary for using the API.)\nAPI URLs closely mirror the URLs of the web application.\n\nAs in the web application, access to data is scoped by vault, so most API\nURLs contain a vault identifier. The majority of API calls return a JSON\nstructure as the response body.\n\n## Object IDs\n\nVaults, saved searches, and other objects are identified by an integer ID.\nWhen you retrieve a list of objects (vaults, saved searches, projects, etc.)\neach object has both a name and an ID, and you typically supply the numeric\nID in subsequent calls. Some parameters take lists of objects, expressed as a\ncomma-separated list of IDs.\n\nThe same IDs appear in the web interface URLs, so you can often copy a number\nfrom the browser into an API call:\n\n- Browser: `https://app.collaborativedrug.com/vaults/4657/searches`\n- API: `https://app.collaborativedrug.com/api/v1/vaults/4657/searches`\n\n## Date and time formats\n\nAny parameter documented as a date accepts ISO 8601 date/time values. You\nmay provide a plain date, like `created_after=2020-05-20`. You may also\nprovide a date plus a timestamp, like `created_after=2020-05-20 14:53:12`,\nwhich is interpreted in the time zone configured on your user account. The\ntimestamp may also include an explicit UTC (Coordinated Universal Time)\noffset, like `created_after=2020-05-27T14:48:40-07:00`, which indicates\nthat the time specified is 7 hours behind UTC.\n\nExcept for Inventory Samples, timestamps are stored with one-second\nprecision, so any fractional seconds you supply are ignored when\nfiltering. Inventory Sample timestamps are stored and filtered with\nmicrosecond precision.\n\n## Authentication & security\n\nEvery request must include your API key in the `X-CDD-Token` header, and all\nrequests must be made over HTTPS so the token and data are encrypted in\ntransit.\n\nAccess is controlled at several levels:\n\n- **Token** — tokens are issued per user/account and carry a role (set of\n capabilities); the effective capabilities depend on the token owner's role\n in the vault(s) being accessed. See the support site for how to obtain a\n token.\n- **Vault** — even with a valid token, data is only available from vaults\n that have API access enabled. A vault administrator can request this by\n emailing CDD Support.\n- **Project** — a user can only access data in projects they have permission\n for. The projects a user can access in a vault can be listed via the API.\n\n## POST `/query` endpoints\n\nMost list and read endpoints accept their parameters either as URL query\nparameters on the `GET` request, or as a JSON body on a companion `POST`\nrequest at the same path with `/query` appended (for example\n`POST /molecules/query` instead of `GET /molecules`). The `/query` form\nexists because many HTTP client libraries cannot send a body with a `GET`\nrequest, and because long or complex filters are easier to express as JSON.\nThe two forms accept the same parameters and return the same responses; the\n`POST /query` form is recommended for anything beyond a trivial request.\n\n## Pagination\n\nList endpoints are paginated. Use `page_size` to set the number of records\nper page (default 50, maximum 1000 for synchronous requests) and `offset` to\nskip records. Paginated responses include the total `count` alongside the\nreturned `objects`. To page through a large result set, increase `offset` by\n`page_size` until you have retrieved `count` records.\n\n## Asynchronous requests (async=true)\n\nFor large result sets, pass async=true to a query endpoint. Instead of\nreturning the data inline, the request creates an export and returns its\ndetails (including an export id). Asynchronous requests are not paginated:\nany `page_size` or `offset` parameter is ignored, and the export contains\nthe complete result set. Poll `GET /export_progress/{export_id}` until the\nexport reports that it is finished, then download the result from\n`GET /exports/{export_id}`. `GET /exports` lists all of your in-progress\nexports (including those started from the web application).\n\n## Rate limits and throttling\n\nCDD Vault does not limit the total number of API requests you can make, but\nit does throttle usage in two ways. Please optimize your integrations to use\nthe API efficiently, and contact CDD Support if any limit poses a problem.\n\n- **3 concurrent requests.** Each user may have up to 3 requests in flight at\n once, so an integration can use up to 3 threads/processes that each issue a\n new request as soon as the previous one completes. This limit is per\n **user**, not per API key — important if you run multiple integrations.\n- **30 queued exports.** Every request that uses `async=true` (and every\n saved-search download) launches a background export. Up to 3 run at a time\n and the rest queue, up to a maximum of 30 queued exports.\n\nUse of the API is monitored; abuse may result in suspension of access and\nfurther investigation.\n",
"license": {
"name": "Proprietary",
"url": "https://support.collaborativedrug.com/hc/en-us/requests/new"
},
"title": "CDD API",
"version": "1.0.0"
},
"servers": [
{
"url": "https://app.collaborativedrug.com/api/v1"
}
],
"security": [
{
"ApiKeyAuth": []
}
],
"tags": [
{
"description": "Track asynchronous API request executions",
"name": "API Executions"
},
{
"description": "Asynchronous batch move jobs",
"name": "Batch Move Jobs"
},
{
"description": "Batches handling",
"name": "Batches"
},
{
"description": "Collections of molecules",
"name": "Collections"
},
{
"description": "Control well layouts for protocols and runs",
"name": "Control Layouts"
},
{
"description": "Public and vault datasets",
"name": "Datasets"
},
{
"description": "Deep learning bioisostere suggestions",
"name": "Deep Learning Bioisosteres"
},
{
"description": "Deep learning molecular similarity",
"name": "Deep Learning Similarity"
},
{
"description": "Protocol dose response calculations management",
"name": "Dose Response Calculations"
},
{
"description": "Dose response data series management",
"name": "Dose Response Data Series"
},
{
"description": "Electronic lab notebook entries",
"name": "ELN Entries"
},
{
"description": "Asynchronous data exports",
"name": "Exports"
},
{
"description": "Vault field definitions",
"name": "Fields"
},
{
"description": "File attachments",
"name": "Files"
},
{
"description": "Import parsers for structured data files",
"name": "Import Parsers"
},
{
"description": "Sample inventory locations",
"name": "Inventory"
},
{
"description": "Inventory samples and their events",
"name": "Inventory Samples"
},
{
"description": "Import mapping templates",
"name": "Mapping Templates"
},
{
"description": "Molecules handling",
"name": "Molecules"
},
{
"description": "Plates of wells",
"name": "Plates"
},
{
"description": "Projects within a vault",
"name": "Projects"
},
{
"description": "Protocols and their readout data",
"name": "Protocols"
},
{
"description": "Rows of protocol readout data",
"name": "Readout Rows"
},
{
"description": "Registration forms",
"name": "Registration Forms"
},
{
"description": "Registration systems",
"name": "Registration Systems"
},
{
"description": "Runs of protocol data",
"name": "Runs"
},
{
"description": "Saved searches",
"name": "Searches"
},
{
"description": "Data import jobs (slurps)",
"name": "Slurps"
},
{
"description": "Vault operational status",
"name": "Status"
},
{
"description": "Users management",
"name": "Users"
},
{
"description": "Vaults management",
"name": "Vaults"
}
],
"paths": {
"/vaults": {
"get": {
"description": "Return a list of accessible vaults",
"operationId": "get_vaults",
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"items": {
"properties": {
"id": {
"example": 489978881,
"type": "integer"
},
"name": {
"example": "McKerrow Vault",
"type": "string"
}
},
"type": "object"
},
"type": "array"
}
}
},
"description": "List of vaults"
},
"401": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error_apikey"
}
}
},
"description": "Missing or invalid API key"
}
},
"summary": "List of vaults",
"tags": [
"Vaults"
]
}
},
"/vaults/{vault_id}/fields": {
"get": {
"description": "Get all the fields both internal and user defined\n",
"operationId": "getFields",
"parameters": [
{
"in": "path",
"name": "vault_id",
"required": true,
"schema": {
"$ref": "#/components/schemas/vault_id"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"items": {
"$ref": "#/components/schemas/fields"
},
"type": "array"
}
}
},
"description": "List of all fields"
},
"401": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error_apikey"
}
}
},
"description": "Missing or invalid API key"
}
},
"summary": "Retrieve all fields",
"tags": [
"Fields"
]
}
},
"/vaults/{vault_id}/fields/{field_id}/pick_list_values": {
"get": {
"description": "List the pick list values for a vault field definition.",
"operationId": "getPickListValues",
"parameters": [
{
"in": "path",
"name": "vault_id",
"required": true,
"schema": {
"$ref": "#/components/schemas/vault_id"
}
},
{
"description": "Numeric identifier of the field definition",
"in": "path",
"name": "field_id",
"required": true,
"schema": {
"type": "integer"
}
},
{
"description": "Maximum number of records to return (default 50, maximum 1000).",
"in": "query",
"name": "page_size",
"schema": {
"type": "integer"
}
},
{
"description": "Number of records to skip (for pagination).",
"in": "query",
"name": "offset",
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"properties": {
"count": {
"type": "integer"
},
"objects": {
"items": {
"$ref": "#/components/schemas/pick_list_value_object"
},
"type": "array"
},
"offset": {
"type": "integer"
},
"page_size": {
"type": "integer"
}
},
"required": [
"count",
"objects"
],
"type": "object"
}
}
},
"description": "A page of pick list values"
},
"401": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error_apikey"
}
}
},
"description": "Missing or invalid API key"
}
},
"summary": "Get pick list values",
"tags": [
"Fields"
]
},
"post": {
"description": "Create a pick list value on a field definition. Requires vault administrator access.",
"operationId": "createPickListValue",
"parameters": [
{
"in": "path",
"name": "vault_id",
"required": true,
"schema": {
"$ref": "#/components/schemas/vault_id"
}
},
{
"description": "Numeric identifier of the field definition",
"in": "path",
"name": "field_id",
"required": true,
"schema": {
"type": "integer"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/pick_list_value_write"
}
}
},
"required": true
},
"responses": {
"201": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/pick_list_value_object"
}
}
},
"description": "The created pick list value"
},
"401": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error_apikey"
}
}
},
"description": "Missing or invalid API key"
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error"
}
}
},
"description": "Validation error"
}
},
"summary": "Create a pick list value",
"tags": [
"Fields"
]
}
},
"/vaults/{vault_id}/fields/{field_id}/pick_list_values/{id}": {
"delete": {
"description": "Delete a pick list value. Requires vault administrator access.",
"operationId": "deletePickListValue",
"parameters": [
{
"in": "path",
"name": "vault_id",
"required": true,
"schema": {
"$ref": "#/components/schemas/vault_id"
}
},
{
"description": "Numeric identifier of the field definition",
"in": "path",
"name": "field_id",
"required": true,
"schema": {
"type": "integer"
}
},
{
"description": "Numeric identifier of the pick list value",
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"properties": {
"message": {
"type": "string"
}
},
"type": "object"
}
}
},
"description": "The pick list value was deleted"
},
"401": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error_apikey"
}
}
},
"description": "Missing or invalid API key"
},
"404": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error"
}
}
},
"description": "Pick list value not found, or vault is unauthorized"
}
},
"summary": "Delete a pick list value",
"tags": [
"Fields"
]
},
"get": {
"description": "Retrieve a single pick list value.",
"operationId": "getPickListValue",
"parameters": [
{
"in": "path",
"name": "vault_id",
"required": true,
"schema": {
"$ref": "#/components/schemas/vault_id"
}
},
{
"description": "Numeric identifier of the field definition",
"in": "path",
"name": "field_id",
"required": true,
"schema": {
"type": "integer"
}
},
{
"description": "Numeric identifier of the pick list value",
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/pick_list_value_object"
}
}
},
"description": "The pick list value"
},
"401": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error_apikey"
}
}
},
"description": "Missing or invalid API key"
},
"404": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error"
}
}
},
"description": "Pick list value not found, or vault is unauthorized"
}
},
"summary": "Get a pick list value",
"tags": [
"Fields"
]
},
"put": {
"description": "Update a pick list value. Requires vault administrator access.",
"operationId": "updatePickListValue",
"parameters": [
{
"in": "path",
"name": "vault_id",
"required": true,
"schema": {
"$ref": "#/components/schemas/vault_id"
}
},
{
"description": "Numeric identifier of the field definition",
"in": "path",
"name": "field_id",
"required": true,
"schema": {
"type": "integer"
}
},
{
"description": "Numeric identifier of the pick list value",
"in": "path",
"name": "id",
"required": true,
"schema": {
"type": "integer"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/pick_list_value_write"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/pick_list_value_object"
}
}
},
"description": "The updated pick list value"
},
"401": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error_apikey"
}
}
},
"description": "Missing or invalid API key"
},
"404": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error"
}
}
},
"description": "Pick list value not found, or vault is unauthorized"
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error"
}
}
},
"description": "Validation error"
}
},
"summary": "Update a pick list value",
"tags": [
"Fields"
]
}
},
"/vaults/{vault_id}/api_executions": {
"get": {
"description": "Return the API usage (both async and sync) in seconds between a particular timeframe. Use after and before parameters to specify a date range. By default and if before is used with no after, the previous 30 days are returned. The time returned is for the current API key only.",
"operationId": "get_api_executions",
"parameters": [
{
"in": "path",
"name": "vault_id",
"required": true,
"schema": {
"$ref": "#/components/schemas/vault_id"
}
},
{
"description": "Start of the date range (YYYY-MM-DDThh:mm:ss±hh:mm). Defaults to 30 days before `before` when omitted.",
"in": "query",
"name": "after",
"required": false,
"schema": {
"format": "date-time",
"type": "string"
}
},
{
"description": "End of the date range (YYYY-MM-DDThh:mm:ss±hh:mm). Defaults to the current date and time when omitted.",
"in": "query",
"name": "before",
"required": false,
"schema": {
"format": "date-time",
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"additionalProperties": {
"properties": {
"after": {
"description": "Start of the measured range.",
"example": "2023-01-01T07:00:00.000Z",
"format": "date-time",
"type": "string"
},
"before": {
"description": "End of the measured range. Only present when the `before` query parameter was supplied on the request.",
"example": "2023-01-22T08:12:34.000Z",
"format": "date-time",
"type": "string"
},
"seconds": {
"description": "Total API time used in the range, in seconds.",
"example": 20.3,
"type": "number"
}
},
"type": "object"
},
"description": "A single-entry object whose key is the name of the API key used for the request (it is the key's name, not a fixed field called `api-key-name`).",
"example": {
"My API key": {
"after": "2023-01-01T07:00:00.000Z",
"before": "2023-01-22T08:12:34.000Z",
"seconds": 20.3
}
},
"type": "object"
}
}
},
"description": "API usage data"
},
"401": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error_apikey"
}
}
},
"description": "Missing or invalid API key"
}
},
"summary": "API usage in seconds",
"tags": [
"API Executions"
]
}
},
"/vaults/{vault_id}/batch_move_jobs": {
"get": {
"description": "Get all batch move jobs. Requires the user to be a vault administrator.",
"operationId": "get_all_batch_move_jobs",
"parameters": [
{
"in": "path",
"name": "vault_id",
"required": true,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"items": {
"$ref": "#/components/schemas/batch_move_job"
},
"type": "array"
}
}
},
"description": "List of all batch move jobs"
},
"401": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error_apikey"
}
}
},
"description": "Missing or invalid API key"
}
},
"summary": "Get all batch move jobs",
"tags": [
"Batch Move Jobs"
]
},
"post": {
"description": "Create a batch move job to move a batch to a different molecule in the same vault. Requires the user to be a vault administrator.",
"operationId": "create_batch_move_job",
"parameters": [
{
"in": "path",
"name": "vault_id",
"required": true,
"schema": {
"type": "integer"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/batch_move_job_create"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/batch_move_job"
}
}
},
"description": "Batch move job created"
},
"401": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error_apikey"
}
}
},
"description": "Missing or invalid API key"
}
},
"summary": "Create a new batch move job",
"tags": [
"Batch Move Jobs"
]
}
},
"/vaults/{vault_id}/batch_move_jobs/{job_id}": {
"delete": {
"description": "Cancel a single batch move job. Once a job has started it can no longer be canceled. Requires the user to be a vault administrator.",
"operationId": "cancel_batch_move_job",
"parameters": [
{
"in": "path",
"name": "vault_id",
"required": true,
"schema": {
"type": "integer"
}
},
{
"in": "path",
"name": "job_id",
"required": true,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/batch_move_job"
}
}
},
"description": "Batch move job canceled"
},
"401": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error_apikey"
}
}
},
"description": "Missing or invalid API key"
},
"405": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/batch_move_job"
}
}
},
"description": "The job is no longer in a cancelable state (it has already started or finished). The current job is returned unchanged."
}
},
"summary": "Cancel a single batch move job",
"tags": [
"Batch Move Jobs"
]
},
"get": {
"description": "Retrieve a single batch move job. Requires the user to be a vault administrator.",
"operationId": "get_single_batch_move_job",
"parameters": [
{
"in": "path",
"name": "vault_id",
"required": true,
"schema": {
"type": "integer"
}
},
{
"in": "path",
"name": "job_id",
"required": true,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/batch_move_job"
}
}
},
"description": "Batch move job details"
},
"401": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/error_apikey"
}
}
},
"description": "Missing or invalid API key"
}
},
"summary": "Retrieve a single batch move job",
"tags": [
"Batch Move Jobs"
]
}
},
"/vaults/{vault_id}/batches": {
"post": {
"description": "The body of the POST must contain a JSON structure specifying the molecule attributes. The structure is roughly the same format as what is returned by a GET call but with some restrictions and additions.\nNote that in a registration vault, POST batch is the only way to create a new molecule, since the registration of a new molecule must be accompanied by a first batch. In this case, the JSON describing the batch will include a \"molecule\" field with detailed information on the new molecule.\n",
"operationId": "createBatch",
"parameters": [
{
"in": "path",
"name": "vault_id",
"required": true,
"schema": {
"$ref": "#/components/schemas/vault_id"
}
}
],
"requestBody": {
"content": {
"application/json": {
# --- truncated at 32 KB (387 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/collaborative-drug-discovery/refs/heads/main/openapi/collaborative-drug-discovery-openapi.json