REST API

Prev

The HTTP interface of the Biotoolkit Monomer Service. It is the interface Ideation and the other Biotoolkit services use, and it is available to your own integrations.

Base URL and Swagger UI

Item Value
Base path https://<host>/HELM2MonomerService/rest
Swagger UI https://<host>/HELM2MonomerService/
OpenAPI document https://<host>/HELM2MonomerService/rest/openapi.json
Version GET /rest/Version returns the deployed service version as plain text

Ask your Discngine contact for the host of your deployment. The Swagger UI is the authoritative description of the request and response schemas for the version you are running.

Authentication

Every request carries a JWT, presented as Authorization: Bearer <token> and issued through the Discngine Admin Center. The token identifies your organisation, and every read and write is scoped to it: you see the public library and your own monomers, and nobody else's. A request without a valid token is answered with 401.

Every write is attributed to the user the token names, in the first of its username, name, login and email claims: that is the account the version history and the audit columns show. A token that names no user is attributed to System.

Public monomers are readable by everyone and writable by nobody: a write against one returns 403.

Error envelope

Errors carry a JSON body with an outcome and a message:

outcome Status Meaning
INVALID_PARAMETER 400 A path or query parameter is not acceptable
NOT_FOUND 404 No monomer, rule or image matches
VALIDATION_FAILED 409 The monomer violates a rule: duplicate symbol, duplicate structure, duplicate name, missing field, malformed R-groups. A duplicate adds conflictingSymbol and conflictingMonomerId, naming the existing monomer; a duplicate name also adds conflictingName.
ALIAS_CONFLICT 409 A name is already taken: an alias equal to a symbol or an alias in your scope, or a new symbol equal to an alias. Adds conflictingAlias when the obstacle is an alias, and conflictingSymbol and conflictingMonomerId naming the monomer that holds the name.
ARCHIVED_MATCH 409 The symbol or structure matches a deleted monomer. Adds matchType and archived[]; revive it, or repeat the PUT with force=true.
MONOMER_UNREADABLE 500 A stored monomer cannot be served, for example because one of its cap groups is not in the vocabulary. Adds kind (CAP_RESOLUTION or STRUCTURE_CONVERSION); the message names the monomer and the reason. Nothing is written by a request that hits it. Report it to Discngine support.
INTERNAL_ERROR 500 Unexpected failure
SERVICE_MISCONFIGURED 503 The deployment is not configured for the operation. Retrying does not help; report it to Discngine support.

503 means the database or the chemistry service is unavailable, and carries Retry-After: 30. 501 means the operation is not supported by the storage backend of the deployment.

Monomers

{polymertype} is PEPTIDE, RNA or CHEM. Read operations also accept ALL.

Method Path Description
GET /monomer/{polymertype} List monomers. Query: monomertype, filter with filterField set to name or symbol (which also matches aliases), limit, offset. The search is case-insensitive. Returns {offset, limit, total, monomers: [...]}; a monomer appears once, under its symbol, however many of its aliases match.
GET /monomer/{polymertype}/{symbolOrId} One monomer. A segment made only of digits is read as an identifier, anything else as a name: a symbol or an alias, matched case-exactly. Pass by=symbol or by=id to force it. Found by an alias, the response is still the monomer's own record, with its real symbol. version=<n> on an identifier returns an archived version.
PUT /monomer/{polymertype}/{symbol} Create or update the monomer with that symbol. Body: a monomer object. force=true registers a new monomer even when a deleted one matches; without it the request is refused with ARCHIVED_MATCH. aliases=replace applies the body's aliases; onStructureConflict=alias turns a known structure into an alias. See Aliases. chiralFlagAbsent sets how a molfile without the chiral flag is read; see Molfiles and the chiral flag.
DELETE /monomer/{polymertype}/{symbolOrId} Delete, archiving the state. force=true also removes the monomer from its monomer sets. purge=true erases the monomer and all its archived versions, irreversibly. force and purge cannot be combined.
GET /monomer/{polymertype}/{id}/versions Archived versions, newest first. Empty for a monomer with no history.
GET /monomer/{polymertype}/{symbolOrId}/stereoAnalysis The stereo analysis of a monomer against the one it was resolved from: monomer, resolvedFrom, sameGraph, compatible, reason, resolvedGroups[], centres[] (one per stereocentre: parentAtom, childAtom, element, parentLabel, childLabel, configuration as same or inverted, verdict) and warnings[]. resolvedFrom is null and centres empty on a monomer with no link. See Enhanced Stereochemistry.
GET /monomer/{polymertype}/{symbolOrId}/stereoisomers The registered stereoisomers of a monomer, in the caller's tenant and the public data: monomer, id, isomerLabel, statement, resolvedFrom and stereoisomers[], one entry per monomer of the same skeleton with relation (enantiomer, racemate, unknownForm, resolvedForm, labelSibling, diastereomer, otherStereoisomer), link (resolvedFrom, resolvedChild or null), id, symbol, name, isomerLabel, statement (abs, &, or, mixed), smiles and status (live or retired). Computed from the stored structures; an empty list for a monomer without stereocentre. See Enhanced Stereochemistry.
POST /monomer/{polymertype}/{id}/revive Put a deleted monomer back under its identifier, with its metadata and set memberships. 409 when a live monomer holds its symbol, name or structure.
POST /monomer/export Export monomers as a file. Body: format (sdf, csv, xlsx, smiles, json), structure (rgroup, the stored form with its attachment points, or capped, each attachment point replaced by its cap group), delimiter for CSV, and monomers (a list of {polymerType, id} or {polymerType, symbol}, at most 5000) or filter (the list route's parameters). Returns {format, structure, filename, contentType, exported, skipped, warnings, content} (contentBase64 for xlsx). The other form travels in each record as RGROUP_CXSMILES or CAPPED_CXSMILES; a monomer that cannot be capped is exported in its stored form with a NOT_CAPPABLE warning. See How to Export Monomers.

Monomer object

{
  "symbol": "Deg",
  "name": "Diethylglycine",
  "polymerType": "PEPTIDE",
  "monomerType": "Backbone",
  "naturalAnalog": "X",
  "smiles": "CCC(CC)(N[*:1])C([*:2])=O",
  "author": "M. Curie",
  "aliases": ["Et2Gly"],
  "isomerLabel": null,
  "resolvedFrom": null,
  "resolvedFromId": null,
  "rgroups": [
    {"label": "R1", "capGroupName": "H",  "capGroupSMILES": "[*:1][H]", "alternateId": "R1-H"},
    {"label": "R2", "capGroupName": "OH", "capGroupSMILES": "O[*:2]",   "alternateId": "R2-OH"}
  ]
}

symbol, name, polymerType, monomerType and a structure, smiles or molfile, are required. id, createDate and versionNo are server-owned and ignored on input. aliases is always present on output, [] when there are none, and lists your organisation's aliases and the public ones; on input it is ignored unless the PUT carries aliases=replace. capGroupSMILES may be omitted: it is derived from the cap group name. See Monomer Fields.

Three fields carry enhanced stereochemistry; see Enhanced Stereochemistry:

Field On input On output
isomerLabel Optional, 10 characters, trimmed. Accepted only on a structure whose canonical key carries an or group. Part of the uniqueness rule next to the structure. Always present, null when unset.
resolvedFrom Optional: the symbol of the monomer this one resolves, in your library or in the public one, live or retired. The structure must then be one of the stereoisomers that monomer stands for, or the request is refused with 409. The symbol, read from the archive when the parent is retired; null when unset.
resolvedFromId Optional, with resolvedFrom: the parent's identifier as read back. Kept as long as it still carries that symbol, so a symbol reused after a retirement cannot repoint the monomer. The parent's identifier.

A smiles is returned as CXSMILES when the structure carries a stereo group, for example C[C@@H](N[*:1])C([*:2])=O |&1:1|; a molfile as V3000.

Molfiles and the chiral flag

Query parameter Values Effect
chiralFlagAbsent racemic (default), absolute How a molfile in the body is read when it draws stereocentres with the chiral flag off and no STEABS, STERAC or STEREL collection. racemic, the MDL standard: all those centres in one &1 group. absolute: as drawn. A molfile with the flag or with collections, and a smiles, are read the same either way. Any other value is a 400.

Accepted on PUT /monomer/{polymertype}/{symbol}, POST /monomer/import and POST /structure/sdf/smiles. See Enhanced Stereochemistry.

A structure stating stereochemistry the library cannot store is refused, with 409 on PUT and a validation: error on an import row, rather than stored as something else:

Message starts with Meaning
Enhanced stereochemistry on bonds (the MDLV30/STEB… collection …) is not supported The molfile carries a STEBABS, STEBRACn or STEBRELn collection: an E/Z mixture, an unknown double-bond geometry or an atropisomer axis group
Axial chirality is not supported (the stereo on atom <n>, …) Stereo on a biaryl axis, an allene end or a spiro ring system that the canonical key cannot keep

Validation messages returned with 409:

Message Meaning
Symbol already exists Creation with a symbol in use
Symbol does not exist Update of an unknown symbol
Duplicate SMILES structure exists Same canonical structure as a live monomer of the polymer type
Monomer has no Symbol, Monomer has no Natural Analog Missing field
Monomer has wrong Monomertype: <value> monomerType names no monomer type, for a creation as for an edit
Monomer has no R-Groups No attachment point in the structure
Number of RGroups does not start by one or does not raise correctly Labels are not R1, R2, … without a gap
Number of R-Groups in Attachmentlist is NOT equal to number of R-Groups in Smiles rgroups and the structure disagree
Labels of RGroups do not match An rgroups label has no dummy atom
An isomer label ('A') is only allowed on a structure that carries an OR enhanced-stereo group … isomerLabel on an absolute or racemic structure, or over 10 characters
Resolved from 'Phx1': no monomer of that symbol in your library or in the public data resolvedFrom unknown, or naming the monomer itself
Resolved from 'Phx1': not the same molecular graph once stereo is removed …, … atom 10 (C) is absolute in the parent and inverted here, … the same stereo statement as the parent: nothing is resolved … The structure is not one of the stereoisomers the parent stands for. The message names the centre or the rule.
The structure of 'Phx1' cannot change: 2 monomer(s) were resolved from it (Phx3, Phx4) … A structure change on a monomer that has resolved children. Everything else about it may change.

A successful PUT carries an X-Monomer-Outcome header: CREATED, UPDATED, or ALIASED when nothing was registered because the symbol became an alias. It may also carry one or more X-Monomer-Warning headers, percent-encoded. The write stands in every case:

  • a resolved monomer settled an or group the same way as the child of a labelled sibling, where mirror images were expected; the same text is in warnings[] of the stereo analysis;
  • a stereo group said nothing about the structure, which is a meso form: The stereo group &1 (atoms 3, 8) says nothing about this structure: inverting its centres gives the same molecule (a meso form), so its centres are registered as absolute. The monomer is keyed as drawn, so the same compound sent again with or without the group is a duplicate.

Stereoisomers of a monomer

GET /monomer/PEPTIDE/Phx3/stereoisomers, for Phx3 registered as the L form resolved from the unknown Phx1 (label A), with Phx4 its D form resolved from Phx2 (label B) and a racemate racPhx:

{
  "monomer": "Phx3",
  "id": 1203,
  "isomerLabel": null,
  "statement": "abs",
  "resolvedFrom": "Phx1",
  "stereoisomers": [
    {
      "relation": "enantiomer",
      "link": null,
      "id": 1204,
      "symbol": "Phx4",
      "name": "D-phenylalanine analogue",
      "isomerLabel": null,
      "statement": "abs",
      "smiles": "O=C([*:2])[C@H](Cc1ccccc1)N[*:1]",
      "status": "live"
    },
    {
      "relation": "unknownForm",
      "link": "resolvedFrom",
      "id": 1201,
      "symbol": "Phx1",
      "name": "Phenylalanine analogue, flask A",
      "isomerLabel": "A",
      "statement": "or",
      "smiles": "O=C([*:2])[C@@H](Cc1ccccc1)N[*:1] |o1:3|",
      "status": "live"
    },
    {
      "relation": "unknownForm",
      "link": null,
      "id": 1202,
      "symbol": "Phx2",
      "name": "Phenylalanine analogue, flask B",
      "isomerLabel": "B",
      "statement": "or",
      "smiles": "O=C([*:2])[C@@H](Cc1ccccc1)N[*:1] |o1:3|",
      "status": "retired"
    },
    {
      "relation": "racemate",
      "link": null,
      "id": 1200,
      "symbol": "racPhx",
      "name": "Phenylalanine analogue, racemate",
      "isomerLabel": null,
      "statement": "&",
      "smiles": "O=C([*:2])[C@@H](Cc1ccccc1)N[*:1] |&1:3|",
      "status": "live"
    }
  ]
}

The same call on Phx1 lists Phx3 as resolvedForm with link: "resolvedChild", Phx4 as resolvedForm, Phx2 as labelSibling and racPhx as racemate. On racPhx, the four others are resolvedForm. Live entries come first, then retired ones; within each group the symbols are sorted. A client that suggests a substitution reads relation and keeps the entries whose status is live.

Aliases

A monomer answers to its symbol and to any number of aliases. Your aliases are visible to your organisation only, and may name your own monomers or public ones; public aliases are read-only. Within a polymer type a name, symbol or alias, points to one monomer, case-sensitively, and an alias cannot contain /. See Monomer Aliases.

Method Path Description
POST /monomer/{polymertype}/{symbolOrId}/aliases Add an alias owned by your organisation. Body: {"alias": "Sar"}. The monomer is addressed as on GET, by identifier, symbol or alias, and may be public. Returns 200 with the monomer and its aliases.
DELETE /monomer/{polymertype}/{symbolOrId}/aliases/{alias} Remove one of your organisation's aliases. Returns 200 with the monomer and its remaining aliases; 404 when your organisation has no alias of that name on the monomer, which is also the answer for a public alias.

{polymertype} is PEPTIDE, RNA or CHEM on these paths. An alias is stored trimmed, case kept, and at most 500 characters long.

On PUT /monomer/{polymertype}/{symbol}:

Query parameter Effect
aliases=replace Your organisation's aliases of the monomer become exactly the body's aliases, in the same transaction as the monomer: names missing from the list are removed, [] removes them all. Public aliases in the list are ignored, so a body read by GET can be sent back unchanged. Without the parameter, the body's aliases is ignored.
onStructureConflict=alias When the structure is already registered under another symbol, the request symbol is added as an alias of that monomer instead of being refused. Nothing else of the body is written. The answer is 200 with X-Monomer-Outcome: ALIASED and the existing monomer. The default, reject, keeps the 409.

A refused alias, 409 ALIAS_CONFLICT or 400 for a / or an over-long name, leaves nothing written. GET /svg/{polymertype}/{name} also accepts an alias. DELETE /monomer/... and the versions and revive paths do not: they take a symbol or an identifier.

HELM validation and conversion in the other Biotoolkit services accept aliases and keep them as written in their output. They read the library through a cache, so a new alias can take up to five minutes to be accepted there.

Bulk import

Method Path Description
POST /monomer/import Import a batch. Body: a JSON array of monomer objects, or multipart/form-data with a file part in JSON, SDF, CSV or XLSX. format= overrides the extension. mode=async queues the job. onStructureConflict=alias registers a known structure under a new symbol as an alias, as on PUT. chiralFlagAbsent sets how the molfiles are read; see Molfiles and the chiral flag.
GET /monomer/import/{jobId} Job status. Redirects with 303 to the result once finished.
GET /monomer/import/{jobId}/result Per-row outcome, status 207.
GET /monomer/import/capabilities The limits of the deployment: row caps, upload size, formats.

A synchronous import returns 207 directly and is limited to 100 rows by default. Above that, or above the upload size, the service answers 413 with the instruction to use mode=async. An asynchronous import returns 202 with a Location header to poll. An organisation is limited to a few submissions per minute and a few concurrent jobs; 429 and 503 name the limit that was hit.

Flat-file conventions for this endpoint: column names are matched ignoring case, spaces, underscores and hyphens; CSV is semicolon-delimited; the rgroups cell is R1:H;R2:OH in one quoted cell; SDF data fields R1 to R10 carry the cap group names. Aliases come from an aliases column or SDF field, /-separated, or a JSON aliases array; they are added to the monomer the row lands on, never removed. Unlike the application's import page, name and monomer_type are required here.

Result body:

{
  "rows": [
    {"index": 0, "symbol": "Ahp", "status": "CREATED", "errors": []},
    {"index": 1, "symbol": "MeNva", "status": "ALREADY_EXISTS_SYMBOL", "errors": ["already-exists: symbol MeNva"]},
    {"index": 2, "symbol": "PEG2", "status": "FAILED", "errors": ["validation: Invalid cap group \"OME\" for R2. Valid values: H, OH, NH2, Azide, Ethynyl"]}
  ],
  "counts": {"created": 1, "updated": 0, "alreadyExists": 1, "duplicateStructure": 0, "failed": 1, "aliased": 0},
  "total": 3
}

Rows keep the input order. ALREADY_EXISTS_SYMBOL and DUPLICATE_STRUCTURE are benign: the monomer is already there. ALIASED, with onStructureConflict=alias, means the row's symbol was added as an alias of the monomer that has the structure, and is counted in aliased. FAILED is the only error status; an alias refused for a row fails that row, with an alias-conflict: message naming the monomer that holds the name. Error strings start with a category, parse:, validation:, conversion:, duplicate-structure:, already-exists:, aliased:, alias-conflict:, timeout:, persist: or failed:, and never contain database or toolkit internals; a reference such as (ref: 1a2b3c4d5e6f) lets Discngine support find the detail. Re-submitting a batch is safe: the key is the symbol within the polymer type.

Cap groups

The cap group vocabulary: the groups that can close an attachment point. Your organisation's vocabulary is the public cap groups plus its own, whose codes never repeat a public one.

Method Path Description
GET /capgroup Your organisation's active vocabulary as {"capGroups": [{"code": "OH", "name": "Hydroxyl", "template": "O[*:{n}]"}, ...]}. template is the cap's SMILES, with {n} standing for the R-group number.
GET /capgroup/manage Every cap group your organisation owns, active or not, and the active public ones: code, name, template, description, active, displayOrder, origin (system or tenant), overridesSystem, and effective (the row your organisation resolves for that code).
POST /capgroup Create a cap group of your organisation. Body: {"code", "name", "template", "description", "active", "displayOrder"}. 201 with the row as /capgroup/manage lists it and a Location of capgroup/{code}; 409 when your organisation already has that code, or when it is the code of a public cap group, active or not, compared case-insensitively.
PUT /capgroup/{code} Replace the name, template, description, active and displayOrder of one of your organisation's cap groups. The code cannot change: a body code that differs from the path is a 400. active: true reactivates it; leaving active out keeps its state.
DELETE /capgroup/{code} Deactivate one of your organisation's cap groups. Returns {"code": ..., "outcome": "deactivated"}.
DELETE /capgroup/{code}?purge=true Delete it instead, only when none of your organisation's monomers uses it: otherwise 409, with the number of monomers in monomers, and the cap group is kept. Deactivate it instead. Returns {"code": ..., "outcome": "purged"}.
POST /capgroup/refresh Reload the service's working copy of the vocabulary, so that a cap group added to it is accepted without a redeployment. Returns {"Refresh": "valid", "capGroups": <n>, ...}, or {"Refresh": "kept", "Reason": ...} with status 200 when nothing usable came back and the vocabulary already in place was kept. It changes nothing in the vocabulary itself.

Rules for a cap group's fields, the same as on the application's Cap groups page: code at most 50 characters, without ,, ; or :, and not manage or refresh; name at most 250 characters, without , or ;; template at most 500 characters, carrying [*:{n}] exactly once and no space; description at most 1000 characters; displayOrder an integer or null. A field that breaks a rule is a 400 naming the field.

The write endpoints address your organisation's cap groups only: a public code, and another organisation's code, are 404, and the public organisation never writes (403). They check no role. Every write reaches the other Biotoolkit services, which reload your vocabulary.

See Attachment Points and CAP Groups and How to Manage Your Organisation's Cap Groups.

Structure conversions

Two conversions that write nothing.

Method Path Description
POST /structure/sdf/smiles The SMILES of each molfile of an SD file, as the service stores structures: canonical, [*:n] attachment points, enhanced-stereo block when there is one. Body: the SD file, text/plain. chiralFlagAbsent as above. Returns {"chiralFlagAbsent": "racemic", "records": [{"index": 1, "smiles": "..."}, {"index": 2, "error": "..."}]}, one entry per record in file order; a record is the text before a $$$$ line.
POST /structure/capped A structure that is not registered, with each R-group replaced by its cap group: the capping of GET /monomer/{polymertype}/{id}/capped, on the body. Body: {"smiles": "...", "rgroups": [{"label": "R1", "capGroupName": "H"}, ...]}. Returns {smiles, molfile, svg}; 422 with CAP_GROUP_UNRESOLVED or NOT_CAPPABLE as on the stored route.

Images

Method Path Description
GET /svg/{polymertype}/{symbol} The stored drawing, image/svg+xml. The segment may also be an alias.
PUT /svg/{polymertype}/{symbol} Regenerate the drawing of one private monomer
PUT /svg/{polymertype} Regenerate the drawings of all private monomers of the type

Rules

HELM business rules, evaluated by the notation toolkit when a sequence is validated.

Method Path Description
GET /rule All rules
GET /rule/{id} One rule
PUT /rule Create or update the rule in the body
DELETE /rule/{id} Delete

Related