API documentation#

All published study data in the app should be downloadable at several different granularities:

  1. Full study metadata and uploaded data spreadsheet for batch downloads under /static/export.

  2. Export UI with selectable bioreplicates per-study under /study/<studyId>/export, for example: SMGDB00000001/export).

  3. Fine-grained API access to entities through their ID or by performing a search.

The following document describes the third functionality, fine-grained API access. To learn more about the first two, take a look at the user documentation in the help files in the “Downloading Data” topic.

For the following examples, we’ll use curl to demonstrate responses. We’ll use a $ROOT_URL that could be set to your localhost installation, or could be the public database:

export ROOT_URL="https://mgrowthdb.gbiomed.kuleuven.be"

The JSON output will be formatted for readability and in some places, truncated with a message like "[...N more entries...]". There will be a general “output structure” description that describes the general shape of the JSON with the types of its fields.

Requests for specific global identifiers like SMGDB00000001 or EMGDB000000026 should work for you as well, so you should be able to replicate them by running them in the console. NCBI IDs and ChEBI IDs should also work for you. However, other numeric ids may be different, since updates to the underlying data might force them to be recreated. Try these out by fetching a specific study or experiment and picking bioreplicate ID or measurement context ID from the public entity’s metadata.

General principles#

There are two types of results from the API:

  • Metadata returned as JSON

  • Measurement data returned in CSV format

The JSON endpoints always end in .json and the CSV ones end in .csv. A single entity might be downloadable in either format if you simply change the suffix. Explore the specific examples below.

The measurementTimeUnits key describes what time units measurements will be fetched in from the CSV endpoints. Right now, the API will always return time in hours (“h”), but this might be a configurable option later. For the moment, you can consider this an informational key, rather than something specific to the particular study or experiment.

Successful results will be returned with an HTTP status code of 200. A request that somehow doesn’t fit the requirements of the API will have a response code of 400 (“bad request”). A request for a missing entity will return the code 404 (“not found”). For a JSON endpoint, the body of an unsuccessful response will have an “error” key that describes the issue. For a CSV endpoint, you can expect an error message as a single line of text.

Types of values#

Decimal values will be encoded as strings, since JSON doesn’t technically support floating-point values.

Timestamps are encoded as ISO 8601-formatted strings. All timestamps should be in UTC (timezone +00:00). In the structure descriptions below, they’ll be indicated as datetime.

Public IDs of studies, experiments, and projects, are also strings, but have a specific structure, a zero-padded number prefixed by “SMGDB”, “EMGDB”, and “PMGDB”, respectively

Technique units depend on what the specific technique is, but they will be one of:

  • Cell count units: Cells/mL, Cells/μL

  • CFU count units: CFUs/mL, CFUs/μL

  • Metabolite units of molar or mass concentration: mM, μM, nM, pM, g/L, mg/L

Units within these three lists are convertible between each other in the application. To request data in specific units, append the corresponding query parameters to each query:

  • cellCountUnits, example: ?cellCountUnits=Cells/μL, default: Cells/mL

  • cfuCountUnits, example: ?cfuCountUnits=CFUs/μL, default: CFUs/mL

  • metaboliteUnits, example: ?metaboliteUnits=g/L, default: mM

For a combined example of all three, you can make a request to a particular endpoint with an added query string:

?cellCountUnits=Cells/μL&cfuCountUnits=CFUs/μL&metaboliteUnits=g/L`

There are also other units that are not convertible with the others:

  • AUC: for metabolites, a relative measurement

  • g/L: for mass concentration of cells, same unit as with metabolites, but non-convertible (since we don’t know the weights of individual cells)

  • reads: for relative cell abundances

  • an empty string, indicating a unitless value like OD or pH.

Below, in the structure descriptions, these will be described as the type Unit. The original units that the data was uploaded in will be labeled “original”, e.g. techniqueOriginalUnits.

Public entity metadata#

There are three major entities with stable public ids: projects, studies, and experiments. We can fetch names, descriptions, and links to other entities from those central objects.

Projects#

Output structure:

{
  id: "PMGDBxxx",
  name: string,
  description: string,
  studies: [{
    id: "SMGDBxxx",
    name: string,
  }]
}

Example project: PMGDB000001.

curl -s "$ROOT_URL/api/v1/project/PMGDB000001.json"

Output:

{
  "id": "PMGDB000001",
  "name": "Synthetic human gut bacterial community using an automated fermentation system",
  "description": "Six biological replicates for a community initially consisting of five common gut bacterial species that fill different metabolic niches. After an initial 12 hours in batch mode, we switched to chemostat mode and observed the community to stabilize after 2-3 days.",
  "studies": [
    {
      "id": "SMGDB00000001",
      "name": "Synthetic human gut bacterial community using an automated fermentation system"
    }
  ]
}

Studies#

Output structure:

{
  id: "SMGDBxxx",
  projectId: "PMGDBxxx",
  name: string,
  description: string,
  url: string,
  uploadedAt: datetime,
  publishedAt: datetime,
  experiments: [{
    id: "EMGDBxxx",
    name: string,
  }]
}

Example study: SMGDB00000002.

curl -s "$ROOT_URL/api/v1/study/SMGDB00000002.json"

Output:

{
  "id": "SMGDB00000002",
  "name": "Starvation responses impact interaction of human gut bacteria BT-RI",
  "projectId": "PMGDB000002",
  "description": "we used an in vitro batch system containing mucin beads to emulate the dynamic host environment and to study its impact on the interactions between two abundant and prevalent human gut bacteria.",
  "url": "https://doi.org/10.1038/s41396-023-01501-1",
  "uploadedAt": "2025-06-05T16:52:49+00:00",
  "publishedAt": "2025-06-05T16:52:53+00:00",
  "experiments": [
    {
      "id": "EMGDB000000019",
      "name": "BT_MUCIN"
    },
    {
      "id": "EMGDB000000020",
      "name": "BT_WC"
    },
    ["...4 more entries..."]
  ]
}

Experiments#

Output structure (note that compartment values encoded as decimal numbers are returned as strings):

{
  id: "EMGDBxxx",
  name: string,
  description: string,
  studyId: "SMGDBxxx",
  cultivationMode: "batch"|"fed-batch"|"chemostat"|"other",
  communityStrains: [{
    id: number,
    NCBId: number,
    custom: boolean,
    name: string,
  }],
  compartments: [{
    name: string,
    volume?: string,
    pressure?: string,
    stirringSpeed?: string,
    stirringMode?: "linear"|"orbital"|"vibrational",
    O2?: string,
    CO2: string,
    H2?: string,
    N2?: string,
    inoculumConcentration?: string,
    inoculumVolume?: string,
    initialPh?: string,
    dilutionRate?: string,
    initialTemperature?: string,
    mediumName?: string,
    mediumUrl?: string,
  }],
  bioreplicates: [{
    id: number,
    name: string
    biosampleUrl?: string,
    isAverage: boolean,
    measurementContexts: [{
      id: number,
      experimentId: "EMGDBxxx",
      studyId: "SMGDBxxx",
      techniqueType: "fc"|"od"|"plates"|"16s"|"qpcr"|"ph"|"metabolite",
      techniqueOriginalUnits: Unit,
      techniqueUnits: Unit,
      subject: {
        type: "bioreplicate"|"strain"|"metabolite",
        name: string,
        NCBId?: number,
        chebiId?: number,
      }
    }]
  }]
}

Example experiment: EMGDB000000019

curl -s "$ROOT_URL/api/v1/experiment/EMGDB000000019.json"

Example output:

{
  "id": "EMGDB000000019",
  "name": "BT_MUCIN",
  "description": "BT with WC plus mucin beads for 120 h",
  "studyId": "SMGDB00000002",
  "cultivationMode": "batch",
  "communityStrains": [
    {
      "id": 60031,
      "NCBId": 818,
      "custom": false,
      "name": "Bacteroides thetaiotaomicron"
    }
  ],
  "compartments": [
    {
      "name": "WC",
      "volume": "60.00",
      "pressure": "1.00",
      "stirringSpeed": 170.0,
      "stirringMode": "linear",
      "O2": null,
      "CO2": "10.00",
      "H2": "10.00",
      "N2": "80.00",
      "inoculumConcentration": "1960000.000",
      "inoculumVolume": "1.00",
      "initialPh": "6.70",
      "dilutionRate": null,
      "initialTemperature": "37.00",
      "mediumName": "Wilkins-Chalgren Anaerobe Broth (WC)",
      "mediumUrl": "https://mediadive.dsmz.de/medium/339"
    },
    {
      "name": "MUCIN",
      "volume": null,
      "pressure": null,
      "stirringSpeed": null,
      "stirringMode": "",
      "O2": null,
      "CO2": null,
      "H2": null,
      "N2": null,
      "inoculumConcentration": null,
      "inoculumVolume": null,
      "initialPh": null,
      "dilutionRate": null,
      "initialTemperature": "37.00",
      "mediumName": "Mucin",
      "mediumUrl": null,
    }
  ],
  "bioreplicates": [
    {
      "id": 60111,
      "name": "Average(BT_MUCIN)",
      "biosampleUrl": null,
      "isAverage": true,
      "measurementContexts": [
        {
          "id": 1431,
          "techniqueType": "od",
          "techniqueOriginalUnits": "",
          "techniqueUnits": "",
          "subject": {
            "id": 60111,
            "type": "bioreplicate",
            "name": "Average(BT_MUCIN)"
          }
        },
        {
          "id": 1432,
          "techniqueType": "ph",
          "techniqueOriginalUnits": "",
          "techniqueUnits": "",
          "subject": {
            "id": 60111,
            "type": "bioreplicate",
            "name": "Average(BT_MUCIN)"
          }
        },
        "[...5 more entries...]"
      ]
    },
    "[...3 more entries...]"
  ]
}

Measurement data#

For a single measurement context#

From one of the above measurement context records, we can find the id of a particular collection of measurements and fetch its metadata as JSON and its specific measurements in CSV format.

Metadata structure:

{
  id: number,
  experimentId: "EMGDBxxx",
  studyId: "SMGDBxxx",
  bioreplicateId: number,
  bioreplicateName: string,
  techniqueType: "fc"|"od"|"plates"|"16s"|"qpcr"|"ph"|"metabolite",
  techniqueOriginalUnits: Unit,
  techniqueUnits: Unit,
  subject: {
    type: "bioreplicate"|"strain"|"metabolite",
    name: string,
    NCBId?: number,
    chebiId?: number,
  },
  measurementCount: number,
  measurementTimeUnits: "h",
}

To fetch the metadata via curl:

curl -s "$ROOT_URL/api/v1/measurement-context/1440.json"

Example output:

{
  "id": 1440,
  "experimentId": "EMGDB000000020",
  "studyId": "SMGDB00000002",
  "bioreplicateId": 60329,
  "bioreplicateName": "Average(BT_WC)",
  "techniqueType": "fc",
  "techniqueOriginalUnits": "Cells/μL",
  "techniqueUnits": "Cells/mL",
  "measurementCount": 14,
  "measurementTimeUnits": "h"
  "modelPredictionIds": [],
  "subject": {
    "type": "strain",
    "name": "Bacteroides thetaiotaomicron VPI-5482",
    "NCBId": 226186
  },
}

This gives us information about the specifics of the measurement context like what its technique is, what units the value is measured in, and the public ids of its containing experiment and study. To fetch the full dataset for this measurement context with “time” measured in hours:

curl -s "$ROOT_URL/api/v1/measurement-context/1440.csv"

Example output:

time,value,std
0.0,2619.0,477.072
4.0,36072.333,1522.018
12.0,1003028.333,30201.503
16.0,1106725.0,85176.706
24.0,857815.0,62848.275
28.0,778893.333,47670.388
32.0,962915.0,55489.511
38.0,675345.0,26650.222
48.0,348478.333,102905.344
60.0,111021.667,28523.155
72.0,45606.667,13966.714
96.0,13413.333,4155.786
120.0,3215.0,461.808

If the measurement context does not have standard deviation values, the “std” column will be present, but empty. Example measurement and its data:

curl -s "$ROOT_URL/api/v1/measurement-context/1314.json"
curl -s "$ROOT_URL/api/v1/measurement-context/1314.csv"
{
  "id": 1314,
  "experimentId": "EMGDB000000020",
  "studyId": "SMGDB00000002",
  "bioreplicateId": 60315,
  "bioreplicateName": "BT_WC_3",
  "techniqueType": "metabolite",
  "techniqueOriginalUnits": "mM",
  "techniqueUnits": "mM",
  "measurementCount": 14,
  "measurementTimeUnits": "h"
  "modelPredictionIds": [],
  "subject": {
    "type": "metabolite",
    "name": "succinate",
    "chebiId": 26806
  },
}
time,value,std
0.0,0.57,
4.0,0.53,
8.0,2.19,
12.0,5.04,
16.0,7.67,
24.0,9.58,
28.0,10.66,
32.0,10.67,
38.0,10.69,
48.0,10.99,
60.0,11.06,
72.0,10.94,
96.0,11.0,
120.0,11.03,

For an entire biological replicate#

We can perform similar queries for biological replicates, getting the results for multiple measurement contexts in one CSV, grouped by measurement context id. We can get the bioreplicate IDs from the experiment metadata and use them to fetch either the bioreplicate-specific metadata or the measurements in CSV form.

Output structure:

{
  id: number,
  experimentId: "EMGDBxxx",
  studyId: "SMGDBxxx",
  name: string,
  biosampleUrl: null,
  isAverage: boolean,
  measurementTimeUnits: "h",
  measurementContexts: [{
    id: number,
    techniqueType: "fc"|"od"|"plates"|"16s"|"qpcr"|"ph"|"metabolite",
    techniqueOriginalUnits: Unit,
    techniqueUnits: Unit,
    subject: {
      type: "bioreplicate"|"strain"|"metabolite",
      name: string,
      NCBId?: number,
      chebiId?: number,
    }
  }]
}

The CSV for a biological replicate includes additional context about the subject of each measurement: its type and name, and external database identifier, if applicable. This information can be seen in the JSON metadata, but it’s included in the CSV for convenience.

curl -s "$ROOT_URL/api/v1/bioreplicate/1314.json"
curl -s "$ROOT_URL/api/v1/bioreplicate/1314.csv"
{
  "id": 60332,
  "experimentId": "EMGDB000000023",
  "studyId": "SMGDB00000002",
  "name": "Average(BTRI_MUCIN)",
  "biosampleUrl": null,
  "isAverage": true,
  "measurementTimeUnits": "h",
  "measurementContexts": [
    {
      "id": 3364,
      "techniqueType": "od",
      "techniqueOriginalUnits": "",
      "techniqueUnits": "",
      "subject": {
        "type": "bioreplicate",
        "name": "Average(BTRI_MUCIN)"
      }
    },
    ["...17 more entries..."]
  ]
}
measurementContextId,subjectType,subjectName,subjectExternalId,time,value,std
3328,bioreplicate,Average(BT_WC),,0.0,0.006,0.001
3328,bioreplicate,Average(BT_WC),,4.0,0.034,0.0
3328,bioreplicate,Average(BT_WC),,8.0,0.406,0.001
3328,bioreplicate,Average(BT_WC),,12.0,0.796,0.002
3328,bioreplicate,Average(BT_WC),,16.0,0.965,0.001
3328,bioreplicate,Average(BT_WC),,24.0,0.705,0.002
3328,bioreplicate,Average(BT_WC),,28.0,0.659,0.003
3328,bioreplicate,Average(BT_WC),,32.0,0.657,0.0
3328,bioreplicate,Average(BT_WC),,38.0,0.868,0.006
3328,bioreplicate,Average(BT_WC),,48.0,0.909,0.003
3328,bioreplicate,Average(BT_WC),,60.0,0.921,0.004
3328,bioreplicate,Average(BT_WC),,72.0,0.92,0.002
3328,bioreplicate,Average(BT_WC),,96.0,0.909,0.002
3328,bioreplicate,Average(BT_WC),,120.0,0.905,0.001
3329,bioreplicate,Average(BT_WC),,0.0,6.613,0.019
3329,bioreplicate,Average(BT_WC),,4.0,6.623,0.019
3329,bioreplicate,Average(BT_WC),,8.0,6.15,0.0
3329,bioreplicate,Average(BT_WC),,12.0,5.42,0.0
3329,bioreplicate,Average(BT_WC),,16.0,5.073,0.024
3329,bioreplicate,Average(BT_WC),,24.0,5.027,0.019
3329,bioreplicate,Average(BT_WC),,28.0,4.97,0.0
3329,bioreplicate,Average(BT_WC),,32.0,4.983,0.019
3329,bioreplicate,Average(BT_WC),,38.0,5.023,0.019
3329,bioreplicate,Average(BT_WC),,48.0,5.14,0.0
3329,bioreplicate,Average(BT_WC),,60.0,5.09,0.0
3329,bioreplicate,Average(BT_WC),,72.0,5.09,0.0
3329,bioreplicate,Average(BT_WC),,96.0,5.14,0.0
3329,bioreplicate,Average(BT_WC),,120.0,5.113,0.024
3330,strain,Bacteroides thetaiotaomicron VPI-5482,NCBI:226186,0.0,2619.0,477.072
3330,strain,Bacteroides thetaiotaomicron VPI-5482,NCBI:226186,4.0,36072.333,1522.018
3330,strain,Bacteroides thetaiotaomicron VPI-5482,NCBI:226186,12.0,1003028.333,30201.503
3330,strain,Bacteroides thetaiotaomicron VPI-5482,NCBI:226186,16.0,1106725.0,85176.706
3330,strain,Bacteroides thetaiotaomicron VPI-5482,NCBI:226186,24.0,857815.0,62848.275
3330,strain,Bacteroides thetaiotaomicron VPI-5482,NCBI:226186,28.0,778893.333,47670.388
3330,strain,Bacteroides thetaiotaomicron VPI-5482,NCBI:226186,32.0,962915.0,55489.511
3330,strain,Bacteroides thetaiotaomicron VPI-5482,NCBI:226186,38.0,675345.0,26650.222
3330,strain,Bacteroides thetaiotaomicron VPI-5482,NCBI:226186,48.0,348478.333,102905.344
3330,strain,Bacteroides thetaiotaomicron VPI-5482,NCBI:226186,60.0,111021.667,28523.155
3330,strain,Bacteroides thetaiotaomicron VPI-5482,NCBI:226186,72.0,45606.667,13966.714
3330,strain,Bacteroides thetaiotaomicron VPI-5482,NCBI:226186,96.0,13413.333,4155.786
3330,strain,Bacteroides thetaiotaomicron VPI-5482,NCBI:226186,120.0,3215.0,461.808
3331,metabolite,pyruvate,CHEBI:15361,0.0,9.663,0.061
3331,metabolite,pyruvate,CHEBI:15361,4.0,9.69,0.127
[...218 more lines...]

Model predictions#

The database includes modeling functionality – users can fit models in the application interface, or they can upload custom models. The modeling records will be returned when fetching measurement contexts in the modelPredictionIds key, which in the examples so far has been empty.

If you have a model prediction id, you can fetch the JSON metadata that describes this fit and a CSV of its predictions from the /model-prediction/ endpoint.

Structure:

{
  id: number,
  measurementContextId: number,
  studyId: "SMGDBxxx",
  type: "easy_linear"|"logistic"|"baranyi_roberts"|"custom_<number>",
  params: dict,
  calculatedAt: datetime,
}

The params dictionary will have variable contents that describe input parameters to the modeling process, quality of fit, growth parameters, and potentially other important information. If the type of the model is a custom one, the type key will start with custom_ but have a variable label.

Example:

curl -s "$ROOT_URL/api/v1/model-prediction/29.json"
curl -s "$ROOT_URL/api/v1/model-prediction/29.csv"
{
  "id": 29,
  "measurementContextId": 9522,
  "studyId": "SMGDB00000007",
  "type": "logistic",
  "params": {
    "fit": {
      "r2": "0.9972",
      "rss": "0.0942"
    },
    "inputs": {
      "endTime": "30"
    },
    "r_version": "4.4.3 (2025-02-28)",
    "coefficients": {
      "K": "858879.5694",
      "y0": "2381.8389",
      "mumax": "0.6582"
    },
    "growthrates_version": "0.8.5"
  },
  "calculatedAt": "Tue, 20 Jan 2026 10:53:39 GMT"
}
time,value,std
0.0,2381.8389,
0.6030150753768844,3537.524301675712,
1.2060301507537687,5250.519088490064,
1.809045226130653,7785.456559068567,
[...196 more lines...]