eTMF
The eTMF (Electronic Trial Master File) API enables you to manage clinical trial documentation programmatically. Use this API to query study details, retrieve filing levels, list artifacts and milestones, and import documents into your studies.
Note: All eTMF API endpoints require the Egnyte.etmf OAuth scope.
Base URL
https://{domain}.egnyte.com/pubapi/v1/etmf
Authentication
All requests require an OAuth 2.0 Bearer token in the Authorization header:
Authorization: Bearer {access_token}
See Authentication for details on obtaining a token with the Egnyte.etmf scope.
List Studies
Retrieve all studies the authenticated user has access to.
Request
GET /pubapi/v1/etmf/studies
Path Parameters
This endpoint does not require path parameters.
Query Parameters
This endpoint does not require query parameters.
Example Request
curl -i -X GET "https://{domain}.egnyte.com/pubapi/v1/etmf/studies" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Response
200 OK
| Field | Type | Description |
|---|---|---|
studies | array | List of study objects |
studies[].systemId | string | Unique system identifier for the study |
studies[].id | string | Human-readable study identifier |
studies[].name | string | Display name of the study |
studies[].description | string | Study description |
studies[].status | string | Study status (e.g., ACTIVE) |
Example Response
{
"studies": [
{
"systemId": "eee92526-53ce-45be-bdce-7263567c9e78",
"id": "DEM-81",
"name": "Demo 81 Study",
"description": "Acme Tx is conducting a study to evaluate the impact of DEM-81 on...",
"status": "ACTIVE"
}
]
}
List Filing Levels
Retrieve the filing level hierarchy (trial, countries, and sites) for a specific study.
Request
GET /pubapi/v1/etmf/studies/{studyId}/filing-levels
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
studyId | string | Yes | System ID of the study |
Example Request
curl -i -X GET "https://{domain}.egnyte.com/pubapi/v1/etmf/studies/{studyId}/filing-levels" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Response
200 OK
| Field | Type | Description |
|---|---|---|
trial | object | Trial-level filing information |
trial.systemId | string | System ID of the trial filing level |
trial.status | string | Trial status (e.g., ACTIVE) |
trial.countries | array | List of countries in the trial |
trial.countries[].systemId | string | System ID of the country filing level |
trial.countries[].code | string | ISO country code |
trial.countries[].status | string | Country status |
trial.countries[].sites | array | List of sites within the country |
trial.countries[].sites[].systemId | string | System ID of the site filing level |
trial.countries[].sites[].id | string | Site identifier |
trial.countries[].sites[].status | string | Site status |
Example Response
{
"trial": {
"systemId": "2f47005e-76d1-42e7-857c-926ca5723e18",
"status": "ACTIVE",
"countries": [
{
"systemId": "5ccfd52a-75f9-49c5-b2e0-177862699ed0",
"code": "POL",
"status": "ACTIVE",
"sites": [
{
"systemId": "ab650679-ac09-4e1e-afd9-13de225ec4af",
"id": "WAW_01",
"status": "ACTIVE"
}
]
}
]
}
}
List Artifacts and Milestones
Retrieve available artifacts and milestones for a specific filing level within a study.
Request
GET /pubapi/v1/etmf/studies/{studyId}/artifacts
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
studyId | string | Yes | System ID of the study |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
filingLevel | string | Yes | Type of filing level. One of: trial, country, site |
filingLevelId | string | Yes | System ID of the filing level |
Example Request
curl -i -X GET "https://{domain}.egnyte.com/pubapi/v1/etmf/studies/{studyId}/artifacts?filingLevel=trial&filingLevelId={filingLevelId}" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Response
200 OK
| Field | Type | Description |
|---|---|---|
artifacts | array | List of artifact objects |
artifacts[].referenceModelArtifactId | string | Reference model artifact identifier |
artifacts[].number | string | Artifact number (e.g., 01.01.01) |
artifacts[].name | string | Artifact name |
artifacts[].isUnblinded | boolean | Whether the artifact is unblinded |
artifacts[].milestoneNumber | integer | Associated milestone number |
milestones | array | List of milestone objects |
milestones[].id | string | Milestone system ID |
milestones[].name | string | Milestone name |
milestones[].number | integer | Milestone number |
milestones[].status | string | Milestone status |
Example Response
{
"artifacts": [
{
"referenceModelArtifactId": "001",
"number": "01.01.01",
"name": "Trial Master File Plan",
"isUnblinded": false,
"milestoneNumber": 2
}
],
"milestones": [
{
"id": "aa9b50b7-f8ad-4cdd-a401-a6d23ee06568",
"name": "Clinical Infrastructure Ready",
"number": 2,
"status": "ACTIVE"
}
]
}
List Documents
Retrieve documents for a specific filing level with optional filtering by zone, artifact, and status. Supports pagination.
Request
POST /pubapi/v1/etmf/studies/{studyId}/documents/listing
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
studyId | string | Yes | System ID of the study |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
filingLevel.type | string | Yes | Filing level type. One of: TRIAL, COUNTRY, SITE |
filingLevel.systemId | string | Yes | System ID of the filing level |
zone | string | No | Filter by zone (format: {number} {name}, e.g., 02 Central Trial Documents) |
artifact | string | No | Filter by artifact (format: {number} {name}, e.g., 02.01.01 Investigator's Brochure) |
status | string | No | Filter by document status. One of: DRAFT, IN_QC, APPROVED, REJECTED |
limit | integer | No | Maximum number of documents to return (1-200). Default: 20 |
offset | integer | No | Zero-based index for pagination. Default: 0 |
Example Request
curl -i -X POST "https://{domain}.egnyte.com/pubapi/v1/etmf/studies/{studyId}/documents/listing" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -d '{ "filingLevel": { "type": "SITE", "systemId": "b53884cf-2bc0-4830-abba-a54c67c25a65" }, "zone": "02 Central Trial Documents", "artifact": "02.01.01 Investigator'
Response
200 OK
| Field | Type | Description |
|---|---|---|
documents | array | List of document objects |
documents[].studyId | string | Study system ID |
documents[].id | string | Document system ID |
documents[].artifact | object | Artifact classification details |
documents[].artifact.artifactNumber | string | Artifact number |
documents[].artifact.artifactName | string | Artifact name |
documents[].artifact.sectionNumber | string | Section number |
documents[].artifact.sectionName | string | Section name |
documents[].artifact.zoneNumber | string | Zone number |
documents[].artifact.zone | string | Zone name |
documents[].artifact.referenceModelArtifactId | string | Reference model artifact ID |
documents[].artifact.isUnblinded | boolean | Whether the artifact is unblinded |
documents[].milestone | object | Associated milestone |
documents[].milestone.name | string | Milestone name |
documents[].milestone.number | integer | Milestone number |
documents[].milestone.id | string | Milestone system ID |
documents[].filingLevel | object | Filing level information |
documents[].filingLevel.type | string | Filing level type |
documents[].file | object | File metadata |
documents[].file.name | string | File name |
documents[].file.entryId | string | File entry ID |
documents[].file.groupId | string | File group ID |
documents[].qualityControl | object | Quality control information |
documents[].qualityControl.dueOn | string | QC due date (ISO 8601 format) |
documents[].qualityControl.status | string | QC status |
offset | integer | Current offset value |
hasMore | boolean | Whether more results are available |
Example Response
{
"documents": [
{
"studyId": "ab650679-ac09-4e1e-afd9-13de225ec4af",
"id": "ab650679-ac09-4e1e-afd9-13de225ec4af",
"artifact": {
"artifactNumber": "02.01.01",
"artifactName": "Investigator's Brochure",
"sectionNumber": "02.01",
"sectionName": "Product and Trial Documentation",
"zoneNumber": "02",
"zone": "Central Trial Documents",
"referenceModelArtifactId": "31",
"isUnblinded": false
},
"milestone": {
"name": "Clinical Infrastructure Ready",
"number": 2,
"id": "45f8cb40-0d8e-4f82-89c3-3708e4b0210d"
},
"filingLevel": {
"type": "TRIAL"
},
"file": {
"name": "Investigator Brochure v1 - 2024-02-14.docx",
"entryId": "17c79408-6faf-4ba4-8be1-0b77a7511e60",
"groupId": "aa5f47a4-4a02-425b-88ec-dcbe7fa7c2c2"
},
"qualityControl": {
"dueOn": "2025-04-12T14:08:14.812Z",
"status": "DRAFT"
}
}
],
"offset": 0,
"hasMore": true
}
Add Documents
Import a document into a study. The file must already exist in the Egnyte file system before calling this endpoint.
Request
POST /pubapi/v1/etmf/studies/{studyId}/documents
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
studyId | string | Yes | System ID of the study |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
filingLevel.type | string | Yes | Filing level type. One of: TRIAL, COUNTRY, SITE |
filingLevel.systemId | string | Yes | System ID of the filing level |
classification.referenceModelArtifactId | string | No | Reference model artifact ID for classification |
classification.milestoneId | string | No | Milestone system ID to associate with the document |
classification.unblinded | boolean | Conditional | Required when the document is unclassified. Indicates whether the document is unblinded |
sourceFile.groupId | string | Yes | Group ID of the file in the Egnyte file system |
Example Request
curl -i -X POST "https://{domain}.egnyte.com/pubapi/v1/etmf/studies/{studyId}/documents" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -d '{ "filingLevel": { "systemId": "aa9b50b7-f8ad-4cdd-a401-a6d23ee06568", "type": "TRIAL" }, "classification": { "referenceModelArtifactId": "001", "milestoneId": "c8cfa0dd-dda3-4089-962d-3d33bb6ae448" }, "sourceFile": { "groupId": "35ed2e11-35e8-4712-b78f-98aceb780ef8" } }'
Response
200 OK
| Field | Type | Description |
|---|---|---|
id | string | System ID of the newly created document |
file | object | File metadata |
file.groupId | string | File group ID |
file.entryId | string | File entry ID |
file.path | string | Full path to the file in the eTMF structure |
Example Response
{
"id": "aa9b50b7-f8ad-4cdd-a401-a6d23ee06568",
"file": {
"groupId": "35ed2e11-35e8-4712-b78f-98aceb780ef8",
"entryId": "5c8598b6-1ab4-45e5-b534-4b60caeddabd",
"path": "/Shared/__eTMF__/STD-001_STAGING/Trial Binder/Artifacts/01 First Country RA Approval/02 Central Trial Documents/02.01 Product and Trial Documentation/02.01.01 Investigator's Brochure/example.pdf"
}
}
Error Codes
| Status | Error | Description | Resolution |
|---|---|---|---|
| 400 | Bad Request | Invalid request body or parameters | Verify all required fields are present and correctly formatted |
| 401 | Unauthorized | Invalid or expired OAuth token | Refresh your OAuth token |
| 403 | Forbidden | Missing Egnyte.etmf scope or insufficient permissions | Ensure your OAuth token includes the Egnyte.etmf scope and the user has access to the study |
| 404 | Not Found | Study, filing level, or file does not exist | Verify the studyId, filingLevelId, or groupId is correct |
| 429 | Rate Limited | Too many requests | Implement exponential backoff; check the Retry-After header |
Code Examples
List Studies
curl -i -X GET "https://{domain}.egnyte.com/pubapi/v1/etmf/studies" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Add Document
curl -i -X POST "https://{domain}.egnyte.com/pubapi/v1/etmf/studies/eee92526-53ce-45be-bdce-7263567c9e78/documents" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -d '{ "filingLevel": { "systemId": "aa9b50b7-f8ad-4cdd-a401-a6d23ee06568", "type": "TRIAL" }, "classification": { "referenceModelArtifactId": "001", "milestoneId": "c8cfa0dd-dda3-4089-962d-3d33bb6ae448" }, "sourceFile": { "groupId": "35ed2e11-35e8-4712-b78f-98aceb780ef8" } }'
Related Resources
- Authentication — How to obtain OAuth tokens with the
Egnyte.etmfscope - File System API — Upload and manage files before importing them into eTMF
- Best Practices — Rate limiting, pagination, and error handling strategies
