/lookup and /synonyms describe the same concept in two different shapes. Nothing here is wrong on its own, but a client that uses both endpoints has to special-case each one, and every divergence is a thing we have to explain in the API documentation rather than something a user can guess.
This came up while documenting the field lists on the improve-documentation branch — the taxa difference in particular is subtle enough that it needed its own paragraph in documentation/Babel.md.
Divergences
Verified against a local Solr loaded with tests/data/test-synonyms.json. For CHEBI:48407:
- Different names for the same field.
label vs preferred_name, and synonyms vs names.
types is biolink:-prefixed by /lookup and bare by /synonyms. A client joining the two has to normalize the prefix itself.
- Absent vs empty.
/lookup builds a LookupResult and so always emits taxa, defaulting to []. /synonyms returns the raw Solr document, and Solr omits an empty multi-valued field entirely — so the key is missing rather than empty.
/synonyms is untyped. /lookup has response_model=List[LookupResult]; /synonyms is Dict[str, Dict], so its shape appears nowhere in the OpenAPI schema and is not validated.
- Solr internals leak through
/synonyms. id, _version_ and curie_suffix are implementation detail of the index, not of the concept.
- Fields only one endpoint has.
/synonyms returns shortest_name_length and taxon_specific, which /lookup drops; /lookup returns score, highlighting, explain and debug, which have no meaning for a direct CURIE fetch.
- A CURIE that isn't in the index comes back from
/synonyms as {"FAKE:9999": {}} — an empty object rather than an omitted key or an explicit null.
Suggested direction
Give /synonyms a real Pydantic response model and make it return the same view of a concept that /lookup does, keeping the search-only fields (score, highlighting, explain, debug) exclusive to /lookup and dropping the Solr internals. That means picking one name per field and one convention for types.
That is a breaking change for /synonyms consumers, so it probably wants to ride along with a version bump, and it may be worth doing at the same time as #227 (bulk-synonyms) so that a new endpoint isn't added in the old shape.
Worth deciding explicitly rather than by default:
Once this is settled, the endpoint-specific caveats in documentation/API.md and the taxa paragraph in documentation/Babel.md can be deleted rather than maintained.
/lookupand/synonymsdescribe the same concept in two different shapes. Nothing here is wrong on its own, but a client that uses both endpoints has to special-case each one, and every divergence is a thing we have to explain in the API documentation rather than something a user can guess.This came up while documenting the field lists on the
improve-documentationbranch — the taxa difference in particular is subtle enough that it needed its own paragraph indocumentation/Babel.md.Divergences
Verified against a local Solr loaded with
tests/data/test-synonyms.json. ForCHEBI:48407:labelvspreferred_name, andsynonymsvsnames.typesisbiolink:-prefixed by/lookupand bare by/synonyms. A client joining the two has to normalize the prefix itself./lookupbuilds aLookupResultand so always emitstaxa, defaulting to[]./synonymsreturns the raw Solr document, and Solr omits an empty multi-valued field entirely — so the key is missing rather than empty./synonymsis untyped./lookuphasresponse_model=List[LookupResult];/synonymsisDict[str, Dict], so its shape appears nowhere in the OpenAPI schema and is not validated./synonyms.id,_version_andcurie_suffixare implementation detail of the index, not of the concept./synonymsreturnsshortest_name_lengthandtaxon_specific, which/lookupdrops;/lookupreturnsscore,highlighting,explainanddebug, which have no meaning for a direct CURIE fetch./synonymsas{"FAKE:9999": {}}— an empty object rather than an omitted key or an explicit null.Suggested direction
Give
/synonymsa real Pydantic response model and make it return the same view of a concept that/lookupdoes, keeping the search-only fields (score,highlighting,explain,debug) exclusive to/lookupand dropping the Solr internals. That means picking one name per field and one convention fortypes.That is a breaking change for
/synonymsconsumers, so it probably wants to ride along with a version bump, and it may be worth doing at the same time as #227 (bulk-synonyms) so that a new endpoint isn't added in the old shape.Worth deciding explicitly rather than by default:
label/preferred_name,synonyms/names)typesisbiolink:-prefixed everywhere or bare everywhere/synonymskeepsshortest_name_lengthandtaxon_specific, and whether/lookupgains themOnce this is settled, the endpoint-specific caveats in
documentation/API.mdand the taxa paragraph indocumentation/Babel.mdcan be deleted rather than maintained.