REST API service layer — thin async functions that map to Synapse REST endpoints. One file per resource type. Called by model layer, never by end users directly.
async def verb_resource(
required_param: str,
optional_param: str = None,
*,
synapse_client: Optional["Synapse"] = None,
) -> Dict[str, Any]:- All functions are
async def synapse_clientis always the last parameter, keyword-only (after*)- Use
Synapse.get_client(synapse_client=synapse_client)to get the client instance - Use
TYPE_CHECKINGguard forSynapseimport — avoids circular dependencies betweenapi/andclient.py
client = Synapse.get_client(synapse_client=synapse_client)
return await client.rest_post_async(uri="/endpoint", body=json.dumps(request))Available methods: rest_get_async, rest_post_async, rest_put_async, rest_delete_async. Pass endpoint=client.fileHandleEndpoint for file handle operations; omit for the default repository endpoint. Use json.dumps() for request bodies — not raw dicts.
- Most functions return raw
Dict[str, Any]— transformation happens in the model layer viafill_from_dict() - Some return typed dataclass instances (e.g.,
EntityHeaderfromentity_services.py) when the data is only used internally - Delete operations return
None
Use helpers from api_client.py:
rest_get_paginated_async()— for GET endpoints with limit/offset. Expectsresultsorchildrenkey in response.rest_post_paginated_async()— for POST endpoints withnextPageToken. Expectspagearray in response. Both are async generators yielding individual items.
Polymorphic entity deserialization via concrete type dispatch. Maps Java class names from core/constants/concrete_types.py to model classes. When adding a new entity type, register the type mapping here.
- Create
synapseclient/api/new_service.py - Add all public functions to
api/__init__.pyimports and__all__— every public function must be re-exported - Use
json.dumps()for request bodies (not dict) - Reference
entity_services.pyfor CRUD pattern,table_services.pyfor pagination pattern