GCITPs API

Read-only, programmatic access to the GCI-TPs transformation-product graph.

API v1 Read-only No key JSON

Swagger UI OpenAPI JSON

Base path
/api/v1/

Overview

One bounded question per request, over plain HTTPS GET. Compounds are addressed by their full uppercase InChIKey (for example CSCPPACGZOOCGX-UHFFFAOYSA-N); graph endpoints answer exactly one :Reaction step, so multi-step questions are built request by request.

Where everything lives
URLWhat it is
/api/This guide.
/api/v1/…The data API. Every endpoint below.
/api/docsSwagger UI - try requests in the browser.
/api/openapi.jsonThe machine-readable contract, for code generators.
Conventions & stability
  • Requests carry path and query parameters only; bodies, unknown parameters and repeated parameters are rejected with 422.
  • Responses are UTF-8 JSON with every field present (missing values are null) and an X-Request-ID header - quote it when reporting a problem. Errors are problem documents.
  • Caching: successful responses carry an ETag; send it back in If-None-Match for an empty 304. Health and error responses are no-store.
  • Names and SMILES are not searched in v1 - use the website's search to find a compound's InChIKey first.
  • Versioning: the version is part of every path. dataset_version at GET /api/v1/ identifies the scientific data release (not set on this server); record it with results you publish. Endpoint groups can be switched off by the operators, and features shows what is enabled. Graph distance is not available in v1.
  • Stored counts such as predecessors_count count relationships, not distinct compounds, and are not recomputed per request.

Quick start

curl
curl "https://<your-gcitps-host>/api/v1/compounds/by-inchikey/CSCPPACGZOOCGX-UHFFFAOYSA-N"
Python, and paging through a list
Python
import requests

BASE = "https://<your-gcitps-host>"

response = requests.get(
    f"{BASE}/api/v1/compounds/by-inchikey/CSCPPACGZOOCGX-UHFFFAOYSA-N",
    timeout=10,
)
response.raise_for_status()      # errors are problem+json documents
compound = response.json()
print(compound["title"], compound["is_dead_end"], compound["successors_count"])

List endpoints return one page at a time in a stable order. has_more says whether another page exists; send next_cursor back unchanged as cursor, with the same compound and direction. Cursors are opaque and signed - one from another request is rejected (422 invalid-cursor).

Python - every page
import time
import requests

BASE = "https://<your-gcitps-host>"


def all_neighbors(inchikey, direction="both"):
    url = f"{BASE}/api/v1/compounds/by-inchikey/{inchikey}/neighbors"
    params = {"direction": direction, "limit": 100}
    while True:
        response = requests.get(url, params=params, timeout=10)
        if response.status_code == 429:          # rate limited: wait as instructed
            time.sleep(int(response.headers.get("Retry-After", "5")))
            continue
        response.raise_for_status()
        page = response.json()
        yield from page["items"]
        if not page["has_more"]:
            return
        params["cursor"] = page["next_cursor"]

Endpoints

All five data endpoints of v1. Example values are illustrative; field names, types and structure are exactly what the API returns.

GET /api/v1/ API information

Service metadata: API version, dataset release, the limits in force and which endpoint groups are enabled. light rate limit

Details

Parameters

None - any query parameter is rejected with 422.

Example

curl
curl "https://<your-gcitps-host>/api/v1/"

Response 200 - what this server answers now

JSON
{
  "name": "GCITPs API",
  "api_version": "v1",
  "dataset_version": null,
  "read_only": true,
  "documentation": "/api/docs",
  "openapi": "/api/openapi.json",
  "limits": {
    "default_page_size": 25,
    "max_page_size": 100,
    "max_reaction_variants_per_pair": 25,
    "light_requests_per_minute": 60,
    "graph_requests_per_minute": 10
  },
  "features": {
    "compound_lookup": true,
    "neighbors": true,
    "reactions": true,
    "graph_distance": false
  }
}

Response fields

Response

FieldTypeMeaning
name string
api_version string
dataset_version string or null Scientific dataset release identifier, or null if not configured.
read_only boolean
documentation string
openapi string
limits ApiLimits
features ApiFeatures

limits

FieldTypeMeaning
default_page_size integer
max_page_size integer
max_reaction_variants_per_pair integer
light_requests_per_minute integer
graph_requests_per_minute integer

features

FieldTypeMeaning
compound_lookup boolean
neighbors boolean
reactions boolean
graph_distance boolean

Notes

  • Never touches the database, so it is the cheapest way to check the service.

Errors

GET /api/v1/compounds/by-inchikey/{inchikey} Compound detail

One compound by its InChIKey: identifiers, name, SMILES, InChI, mass, synonyms, the dead-end and PMT flags and the stored relationship counts. light rate limit

Details

Parameters

NameInTypeRequiredValuesDescription
inchikey path string yes full uppercase InChIKey, 27 characters (14-10-1 letters) For example CSCPPACGZOOCGX-UHFFFAOYSA-N. Lowercase, partial keys, names or SMILES are rejected (422), not converted.

Example

curl
curl "https://<your-gcitps-host>/api/v1/compounds/by-inchikey/CSCPPACGZOOCGX-UHFFFAOYSA-N"

Response 200

JSON
{
  "inchikey": "CSCPPACGZOOCGX-UHFFFAOYSA-N",
  "gcitps_id": "CSCPPACGZOOCGX",
  "title": "Acetone",
  "smiles": "CC(C)=O",
  "mass": 58.041865,
  "is_dead_end": false,
  "is_pmt": false,
  "predecessors_count": 120,
  "successors_count": 4,
  "synonyms": [
    "acetone",
    "propan-2-one",
    "2-propanone"
  ],
  "synonyms_truncated": false,
  "inchi": "InChI=1S/C3H6O/c1-3(2)4/h1-2H3",
  "deadend_in_count": 0,
  "deadend_out_count": 3
}

Response fields

FieldTypeMeaning
inchikey string Full InChIKey (unique identifier).
gcitps_id string or null Stored GCITPs_ID (first InChIKey block at import).
title string or null Primary compound name, when one exists.
smiles string or null
mass number or null Major isotope mass as stored.
is_dead_end boolean True when the stored is_deadend_product flag is true (the website's 'Dead-end TPs' definition).
is_pmt boolean or null InChIKey is in the curated dead-end PMT/PvM list (the website's 'Dead-end PMT TPs'). Null when that list is unavailable.
predecessors_count integer Stored count of incoming :Reaction relationships (edge count); 0 when no count is stored.
successors_count integer Stored count of outgoing :Reaction relationships (edge count); 0 when no count is stored.
synonyms array of string Stored synonyms, de-duplicated, at most 100 and within the response size budget.
synonyms_truncated boolean True when more synonyms exist than were returned (count cap or size budget).
inchi string or null
deadend_in_count integer Precomputed number of incoming :deadend relationships as stored.
deadend_out_count integer Precomputed number of outgoing :deadend relationships as stored.

Notes

  • One indexed lookup; database time limit 1 s.
  • At most 100 synonyms are returned - synonyms_truncated marks more.

Errors

GET /api/v1/compounds/by-inchikey/{inchikey}/status Compound status

Only the flags and precomputed counts - the smallest answer to “is this a dead-end TP, and how connected is it?”. light rate limit

Details

Parameters

NameInTypeRequiredValuesDescription
inchikey path string yes full uppercase InChIKey, 27 characters (14-10-1 letters) For example CSCPPACGZOOCGX-UHFFFAOYSA-N. Lowercase, partial keys, names or SMILES are rejected (422), not converted.

Example

curl
curl "https://<your-gcitps-host>/api/v1/compounds/by-inchikey/CSCPPACGZOOCGX-UHFFFAOYSA-N/status"

Response 200

JSON
{
  "inchikey": "CSCPPACGZOOCGX-UHFFFAOYSA-N",
  "is_dead_end": false,
  "is_pmt": false,
  "predecessors_count": 120,
  "successors_count": 4,
  "deadend_in_count": 0,
  "deadend_out_count": 3
}

Response fields

FieldTypeMeaning
inchikey string
is_dead_end boolean Stored is_deadend_product flag is true.
is_pmt boolean or null In the curated dead-end PMT/PvM list; null when unavailable.
predecessors_count integer
successors_count integer
deadend_in_count integer
deadend_out_count integer

Notes

  • Nothing is counted live; database time limit 1 s.

Errors

GET /api/v1/compounds/by-inchikey/{inchikey}/neighbors One-step neighbours

Distinct compounds exactly one :Reaction step before (predecessors) or after (successors) the compound. graph rate limit

Details

Parameters

NameInTypeRequiredValuesDescription
inchikey path string yes full uppercase InChIKey, 27 characters (14-10-1 letters) For example CSCPPACGZOOCGX-UHFFFAOYSA-N. Lowercase, partial keys, names or SMILES are rejected (422), not converted.
direction query string no predecessors | successors | both; default both Which side of the compound to list.
limit query integer no 1-100; default 25 Page size.
cursor query string no at most 512 characters The next_cursor of the previous page of the same request (same compound and direction), passed back unchanged.

Example

curl
curl "https://<your-gcitps-host>/api/v1/compounds/by-inchikey/CSCPPACGZOOCGX-UHFFFAOYSA-N/neighbors?direction=successors&limit=1"

Response 200

JSON
{
  "inchikey": "CSCPPACGZOOCGX-UHFFFAOYSA-N",
  "direction": "successors",
  "limit": 1,
  "items": [
    {
      "inchikey": "QTBSBXVTEAMEQO-UHFFFAOYSA-N",
      "gcitps_id": "QTBSBXVTEAMEQO",
      "title": "Acetic acid",
      "smiles": "CC(=O)O",
      "mass": 60.021129,
      "is_dead_end": false,
      "is_pmt": false,
      "predecessors_count": 950,
      "successors_count": 2,
      "is_predecessor": false,
      "is_successor": true
    }
  ],
  "has_more": true,
  "next_cursor": "v1.eyJhIjoiQ1NDUFBBQ0daT09DR1gtVUhGRkZBT1lTQS1OIiwiZCI6InN1Y2Nlc3NvcnMiLCJrIjpbIlFUQlNCWFZURUFNRVFPLVVIRkZGQU9ZU0EtTiJdLCJ0IjoibmVpZ2hib3JzIn0.NrEZPcRK38xn29sMHRXnwg",
  "stored_counts": {
    "predecessors_count": 120,
    "successors_count": 4
  }
}

Response fields

Response

FieldTypeMeaning
inchikey string
direction Literal['predecessors', 'successors', 'both']
limit integer
items array of NeighborItem Distinct one-hop neighbors ordered by inchikey. May hold fewer than `limit` items when the response size budget is reached; `has_more` then stays true.
has_more boolean
next_cursor string or null
stored_counts StoredCounts The anchor's precomputed counts as stored; not a live count of paginated items.

items[]

FieldTypeMeaning
inchikey string Full InChIKey (unique identifier).
gcitps_id string or null Stored GCITPs_ID (first InChIKey block at import).
title string or null Primary compound name, when one exists.
smiles string or null
mass number or null Major isotope mass as stored.
is_dead_end boolean True when the stored is_deadend_product flag is true (the website's 'Dead-end TPs' definition).
is_pmt boolean or null InChIKey is in the curated dead-end PMT/PvM list (the website's 'Dead-end PMT TPs'). Null when that list is unavailable.
predecessors_count integer Stored count of incoming :Reaction relationships (edge count); 0 when no count is stored.
successors_count integer Stored count of outgoing :Reaction relationships (edge count); 0 when no count is stored.
is_predecessor boolean A :Reaction relationship points from this compound to the anchor.
is_successor boolean A :Reaction relationship points from the anchor to this compound.

stored_counts

FieldTypeMeaning
predecessors_count integer
successors_count integer

Notes

  • Ordered by InChIKey and paginated - pass next_cursor back as cursor for the next page.
  • Compounds with more direct reactions than the live query budget are refused before any work is done (422 traversal-too-large).
  • Database time limit 2 s.

Errors

GET /api/v1/compounds/by-inchikey/{inchikey}/reactions One-step reactions

The :Reaction relationships between the compound and each direct neighbour, one item per (neighbour, direction) pair. graph rate limit

Details

Parameters

NameInTypeRequiredValuesDescription
inchikey path string yes full uppercase InChIKey, 27 characters (14-10-1 letters) For example CSCPPACGZOOCGX-UHFFFAOYSA-N. Lowercase, partial keys, names or SMILES are rejected (422), not converted.
direction query string no in | out | both; default both in: reactions producing the compound; out: reactions transforming it.
limit query integer no 1-100; default 25 Page size.
cursor query string no at most 512 characters The next_cursor of the previous page of the same request (same compound and direction), passed back unchanged.

Example

curl
curl "https://<your-gcitps-host>/api/v1/compounds/by-inchikey/CSCPPACGZOOCGX-UHFFFAOYSA-N/reactions?direction=out&limit=1"

Response 200

JSON
{
  "inchikey": "CSCPPACGZOOCGX-UHFFFAOYSA-N",
  "direction": "out",
  "limit": 1,
  "items": [
    {
      "direction": "out",
      "source_inchikey": "CSCPPACGZOOCGX-UHFFFAOYSA-N",
      "target_inchikey": "QTBSBXVTEAMEQO-UHFFFAOYSA-N",
      "reaction_count": 2,
      "reactions": [
        {
          "module": "Environmental",
          "reaction_rule": "EAWAG_RULE_BT0063_PATTERN2",
          "enzymes": "Unspecified environmental bacterial enzyme",
          "biosystem": "ENVMICRO",
          "occurrences": 1
        },
        {
          "module": "Abiotic",
          "reaction_rule": "Hydrogenolysis",
          "enzymes": "AbioticReductionReactionClass",
          "biosystem": "ABIOTIC",
          "occurrences": 1
        }
      ],
      "reactions_truncated": false
    }
  ],
  "has_more": true,
  "next_cursor": "v1.eyJhIjoiQ1NDUFBBQ0daT09DR1gtVUhGRkZBT1lTQS1OIiwiZCI6Im91dCIsImsiOlsiUVRCU0JYVlRFQU1FUU8tVUhGRkZBT1lTQS1OIiwib3V0Il0sInQiOiJyZWFjdGlvbnMifQ.incqgh_7_CbGbzM0IbCqwQ"
}

Response fields

Response

FieldTypeMeaning
inchikey string
direction Literal['in', 'out', 'both']
limit integer
items array of ReactionPairItem One item per one-hop compound pair, ordered by (other compound inchikey, direction). May hold fewer than `limit` items when the response size budget is reached; `has_more` then stays true.
has_more boolean
next_cursor string or null

items[]

FieldTypeMeaning
direction Literal['in', 'out'] Relative to the anchor compound.
source_inchikey string
target_inchikey string
reaction_count integer Total :Reaction relationships from source to target.
reactions array of ReactionVariant Distinct (module, reaction_rule, enzymes, biosystem) combinations in that order, at most 25.
reactions_truncated boolean True when more than 25 distinct combinations exist.

items[].reactions[]

FieldTypeMeaning
module string or null Transformation module, e.g. Abiotic, Environmental.
reaction_rule string or null Name of the transformation (reaction) rule.
enzymes string or null Enzyme or condition label(s) as stored.
biosystem string or null Biosystem, e.g. ABIOTIC.
occurrences integer Number of :Reaction relationships between this pair with exactly these values.

Notes

  • Each item lists the distinct combinations of module, reaction rule, enzymes and biosystem (at most 25; reactions_truncated marks more) with how often each occurs.
  • Same live query budget as neighbours; database time limit 2 s.

Errors

Service status

For monitoring, not for reading data.

GET /api/v1/health/live Liveness

Whether the API process is running. no rate limit

Details

Parameters

None - any query parameter is rejected with 422.

Example

curl
curl "https://<your-gcitps-host>/api/v1/health/live"

Response 200 - what this server answers now

JSON
{
  "status": "ok"
}

Response fields

FieldTypeMeaning
status Literal['ok']

Notes

  • Never touches the database and is not rate limited.
  • Meant for monitoring; a data client does not need it.

Errors

GET /api/v1/health/ready Readiness

Whether the database answers; 503 when it does not. health rate limit

Details

Parameters

None - any query parameter is rejected with 422.

Example

curl
curl "https://<your-gcitps-host>/api/v1/health/ready"

Response 200

JSON
{
  "status": "ok"
}

Response fields

FieldTypeMeaning
status Literal['ok']

Notes

  • Runs a trivial statement with the 1 s time limit.
  • Has its own rate-limit bucket, and operators may restrict it to their monitoring address - so do not build a client around it.

Errors

Errors & limits

Errors are problem documents (application/problem+json): type identifies the problem and is stable, title and detail are for people.

StatusMeaning
404No compound with that InChIKey.
422A parameter, cursor or request is invalid.
429Rate limited - wait for Retry-After seconds.
503Query timed out, or the service is temporarily unavailable.
LimitOn this server
Light requests60 per minute per client
Graph requests10 per minute per client
Page size1-100 (default 25)
Database time1 s lookups, 2 s graph

Limits are counted over a rolling 60-second window per client address; 429 carries a Retry-After header in seconds. A 503 query-timeout means the question was too expensive to answer - retrying immediately will usually fail the same way.

Every problem type, and the remaining limits
StatustypeMeaning
404/api/problems/not-foundNo compound with that InChIKey, or no such path.
405/api/problems/method-not-allowedThe API is read-only; only GET is supported.
414/api/problems/uri-too-longPath or query string longer than allowed.
422/api/problems/validation-errorA parameter is invalid, unknown, or given twice; or a body was sent. errors lists each problem.
422/api/problems/invalid-cursorThe cursor is malformed, expired, or belongs to another request.
422/api/problems/traversal-too-largeThe compound has more direct reactions than the live API serves.
422/api/problems/traversal-size-unknownThe stored counts needed to bound the request are missing.
429/api/problems/rate-limitedToo many requests from your address; wait for Retry-After seconds.
429/api/problems/capacity-exhaustedThe endpoint is at its concurrent-query capacity; retry shortly.
431/api/problems/headers-too-largeRequest headers larger than allowed.
503/api/problems/query-timeoutThe query hit its time limit and was stopped. Nothing is retried for you.
503/api/problems/service-unavailableThe database is temporarily unavailable.
503/api/problems/endpoint-disabledThis endpoint group is switched off (see features).
503/api/problems/api-disabledThe whole API is switched off.
LimitOn this serverOtherwise
Reaction variants25 per compound pairreactions_truncated
Synonyms100 per compoundsynonyms_truncated
URLpath ≤ 256 bytes, query ≤ 1024 bytes414
Headers≤ 8 KB431
404 - unknown compound
{
  "type": "/api/problems/not-found",
  "title": "Not found",
  "status": 404,
  "detail": "No compound with InChIKey CSCPPACGZOOCGX-UHFFFAOYSA-N.",
  "request_id": "5f0c9a1e2b7d4c43a8e61f0b9d2c7e31"
}
422 - invalid parameter
{
  "type": "/api/problems/validation-error",
  "title": "Request validation failed",
  "status": 422,
  "detail": "One or more request parameters are invalid.",
  "request_id": "5f0c9a1e2b7d4c43a8e61f0b9d2c7e31",
  "errors": [
    {
      "location": "query.limit",
      "message": "Input should be less than or equal to 100"
    }
  ]
}

429 capacity-exhausted means the server is briefly busy for everyone. The limits in force are also published at GET /api/v1/ under limits; please cache results you reuse instead of asking again.