Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,49 @@ jobs:
poetry publish --build --no-interaction -r pypi
$version = poetry version
Write-Host "Published ``$version`` to Pypi." >> $Env:GITHUB_STEP_SUMMARY

csharp:
name: CSharp
permissions:
id-token: write
contents: read
packages: write
needs:
- test
- version
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup .NET
uses: actions/setup-dotnet@v5.2.0 # v5.2.0
with:
dotnet-version: |
8.0.x
10.0.x
- name: Restore dotnet tools
working-directory: dotnet
run: dotnet tool restore
- name: Check formatting
working-directory: dotnet
run: dotnet csharpier check .
- name: Restore dependencies
working-directory: dotnet
run: dotnet restore OrchestrateSDK.DotNet.sln
- name: Pack
working-directory: dotnet
run: dotnet pack src/CareEvolution.Orchestrate/CareEvolution.Orchestrate.csproj --configuration Release --no-restore -p:Version=${{ needs.version.outputs.version }} -o ./artifacts
- name: Upload package artifact
if: needs.version.outputs.target == 'dev'
uses: actions/upload-artifact@v4
with:
name: csharp-nuget-package-${{ needs.version.outputs.version }}
path: dotnet/artifacts/*.nupkg
- name: Publish NuGet
if: needs.version.outputs.target == 'prod'
working-directory: dotnet
run: |
dotnet nuget push ./artifacts/*.nupkg \
--source https://proget.careevolution.com/nuget/nuget/ \
--api-key ${{ secrets.PROGET_TOKEN }} \
--skip-duplicate
echo "Published `${{ needs.version.outputs.version }}` to NuGet.org." >> $GITHUB_STEP_SUMMARY
34 changes: 34 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
name: Test

permissions:
contents: read

on:
push:
branches:
Expand Down Expand Up @@ -117,3 +120,34 @@ jobs:
- name: Test
working-directory: python
run: poetry run pytest -m "${{ (inputs.suite || 'default') }}"

csharp:
name: CSharp
runs-on: ubuntu-latest
needs:
- python
strategy:
fail-fast: true
matrix:
dotnet-version: ["8.0.x", "10.0.x"]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup .NET
uses: actions/setup-dotnet@v5.2.0 # v5.2.0
with:
dotnet-version: ${{ matrix.dotnet-version }}
- name: Restore dotnet tools
working-directory: dotnet
run: dotnet tool restore
- name: Check formatting
working-directory: dotnet
run: dotnet csharpier check .
- name: Restore dependencies
working-directory: dotnet
run: dotnet restore OrchestrateSDK.DotNet.sln
- name: Build
working-directory: dotnet
run: dotnet build OrchestrateSDK.DotNet.sln --configuration Release --no-restore
- name: Test
working-directory: dotnet
run: dotnet test OrchestrateSDK.DotNet.sln --configuration Release --no-build
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
**/.mypy_cache/
**/.pytest_cache/
**/.ipynb_checkpoints/
**/__pycache__/
**/__pycache__/
.codex
8 changes: 5 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
# Orchestrate SDK Contribution Guide

The Orchestrate SDK is a TypeScript and JavaScript library for interacting with the Orchestrate API at <https://api.careevolutionapi.com>. Releases are tagged and generated from `main`. Development should be forked from `main` and a PR created to merge back into it.
The Orchestrate SDK is a TypeScript, Python, and C# library for interacting with the Orchestrate API at <https://api.careevolutionapi.com>. Releases are tagged and generated from `main`. Development should be forked from `main` and a PR created to merge back into it.

## Installation

For TypeScript, navigate to the `./typescript` directory and install dependencies with `npm i`. For Python, navigate to the `./python` directory and install dependencies with `poetry install`.
For TypeScript, navigate to the `./typescript` directory and install dependencies with `npm i`.
For Python, navigate to the `./python` directory and install dependencies with `poetry install`.
For C#, navigate to the `./dotnet` directory and restore dependencies with `dotnet restore`.

## Tests

TypeScript tests can be run and watched with `npm run test:watch`. Python tests can be run with `poetry run pytest`.
TypeScript tests can be run and watched with `npm run test:watch`. Python tests can be run with `poetry run pytest`. C# tests can be run with `dotnet test`.

To run Local Hashing Service tests, docker must be installed and running. Tests against the Identity API do not use data directly from the Local Hashing Service, so any valid hash key can be used to start the container. See the [Orchestrate Docs](https://orchestrate.docs.careevolution.com/identity/local_hash/hosting.html) for information on starting the container.
65 changes: 57 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Orchestrate SDK

The Orchestrate SDK is a TypeScript and JavaScript library for interacting with the Orchestrate API at <https://api.careevolutionapi.com>.
The Orchestrate SDK provides TypeScript, Python, and C# clients for interacting with the Orchestrate API at <https://api.careevolutionapi.com>.

Full documentation of the API is available at <https://rosetta-api.docs.careevolution.com/>.

Expand All @@ -18,9 +18,15 @@ Python:
pip install orchestrate-api
```

C#:

```bash
dotnet add package CareEvolution.Orchestrate
```

## Usage

TypeScript:
### TypeScript

```typescript
import { OrchestrateApi } from '@careevolution/orchestrate';
Expand All @@ -32,7 +38,7 @@ await orchestrate.terminology.classifyCondition({
});
```

Python:
### Python

```python
from orchestrate import OrchestrateApi
Expand All @@ -41,11 +47,38 @@ api = OrchestrateApi(api_key="your-api-key")
api.terminology.classify_condition(code="119981000146107", system="SNOMED")
```

### C\#

```csharp
using CareEvolution.Orchestrate;

var api = new OrchestrateApi(new OrchestrateClientOptions
{
ApiKey = "your-api-key",
});

await api.Terminology.ClassifyConditionAsync(new ClassifyConditionRequest
{
Code = "119981000146107",
System = "SNOMED",
});
```

Additionally, C# also supports dependency injection with `IOrchestrateApi` and `OrchestrateApi` registered in the service collection.

```csharp
using CareEvolution.Orchestrate;
using Microsoft.Extensions.DependencyInjection;

var services = new ServiceCollection();
services.AddOrchestrateApi();
```
Comment on lines +69 to +75
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The DI example uses ServiceCollection but doesn’t show the required using Microsoft.Extensions.DependencyInjection; (and readers may not realize the package/reference needed). Consider adding the missing using in the snippet (or a short note) so the example compiles as-is.

Copilot uses AI. Check for mistakes.

## Configuration

The SDK supports environment variables for configuring HTTP behavior. These can be used for local development, CI, or shared runtime configuration.

For the primary `OrchestrateApi` clients in both TypeScript and Python:
For the primary `OrchestrateApi` clients in TypeScript, Python, and C#:

| Environment variable | Purpose | Default |
| --- | --- | --- |
Expand All @@ -60,7 +93,7 @@ Environment variables used by the identity clients:
| --- | --- |
| `ORCHESTRATE_IDENTITY_URL` | Base URL for `IdentityApi`. Required unless the URL is passed directly when creating the client. |
| `ORCHESTRATE_IDENTITY_API_KEY` | API key sent as the `x-api-key` header for `IdentityApi`. |
| `ORCHESTRATE_IDENTITY_METRICS_KEY` | Metrics key sent as the `Authorization` header for `IdentityApi`. A value with or without the `Basic ` prefix is accepted. |
| `ORCHESTRATE_IDENTITY_METRICS_KEY` | Metrics key sent as the `Authorization` header for `IdentityApi`. A value with or without the `Basic` prefix is accepted. |
| `ORCHESTRATE_IDENTITY_LOCAL_HASHING_URL` | Base URL for `LocalHashingApi`. Required unless the URL is passed directly when creating the client. |

### Configuration Precedence
Expand All @@ -71,13 +104,13 @@ When the same setting is provided in more than one place, the SDK resolves it in
2. The matching environment variable
3. The SDK default, when one exists

For example, passing `api_key` or `timeout_ms` in Python, or `apiKey` or `timeoutMs` in TypeScript, overrides the corresponding environment variable.
For example, passing `api_key` or `timeout_ms` in Python, `apiKey` or `timeoutMs` in TypeScript, or `ApiKey` or `TimeoutMs` in C# overrides the corresponding environment variable.

`ORCHESTRATE_ADDITIONAL_HEADERS` is additive. It is merged into the request headers before the SDK applies its standard `Accept`, `Content-Type`, authentication, and metrics headers, so the SDK-managed headers take precedence if the same header name is supplied in multiple places.

### Examples

TypeScript:
#### TypeScript Example

```bash
export ORCHESTRATE_API_KEY="your-api-key"
Expand All @@ -91,7 +124,7 @@ import { OrchestrateApi } from '@careevolution/orchestrate';
const orchestrate = new OrchestrateApi();
```

Python:
#### Python Example

```bash
export ORCHESTRATE_API_KEY="your-api-key"
Expand All @@ -104,3 +137,19 @@ from orchestrate import OrchestrateApi

api = OrchestrateApi()
```

#### C\# Example

With environment values as above or DI configuration:

```csharp
using Microsoft.Extensions.DependencyInjection;
using CareEvolution.Orchestrate;

var services = new ServiceCollection();
services.AddOrchestrateApi(options =>
{
options.ApiKey = "your-api-key";
options.TimeoutMs = 30000;
});
```
13 changes: 13 additions & 0 deletions dotnet/.config/dotnet-tools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"version": 1,
"isRoot": true,
"tools": {
"csharpier": {
"version": "1.2.6",
"commands": [
"csharpier"
],
"rollForward": false
}
}
}
3 changes: 3 additions & 0 deletions dotnet/.csharpierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
**/bin
**/obj
tests/CareEvolution.Orchestrate.Tests/LiveData/**
3 changes: 3 additions & 0 deletions dotnet/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
**/bin/
**/obj/
TestResults/
27 changes: 27 additions & 0 deletions dotnet/OrchestrateSDK.DotNet.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CareEvolution.Orchestrate", "src/CareEvolution.Orchestrate/CareEvolution.Orchestrate.csproj", "{B21EA726-0E99-4CDB-8F56-7A3300565A0B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CareEvolution.Orchestrate.Tests", "tests/CareEvolution.Orchestrate.Tests/CareEvolution.Orchestrate.Tests.csproj", "{3259B89E-A60A-432D-A4B5-547646506A24}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B21EA726-0E99-4CDB-8F56-7A3300565A0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B21EA726-0E99-4CDB-8F56-7A3300565A0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B21EA726-0E99-4CDB-8F56-7A3300565A0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B21EA726-0E99-4CDB-8F56-7A3300565A0B}.Release|Any CPU.Build.0 = Release|Any CPU
{3259B89E-A60A-432D-A4B5-547646506A24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3259B89E-A60A-432D-A4B5-547646506A24}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3259B89E-A60A-432D-A4B5-547646506A24}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3259B89E-A60A-432D-A4B5-547646506A24}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
3 changes: 3 additions & 0 deletions dotnet/src/CareEvolution.Orchestrate/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("CareEvolution.Orchestrate.Tests")]
6 changes: 6 additions & 0 deletions dotnet/src/CareEvolution.Orchestrate/BatchRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace CareEvolution.Orchestrate;

internal sealed class BatchRequest<T>
{
public required IReadOnlyList<T> Items { get; init; }
}
6 changes: 6 additions & 0 deletions dotnet/src/CareEvolution.Orchestrate/BatchResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace CareEvolution.Orchestrate;

internal sealed class BatchResponse<T>
{
public required List<T> Items { get; init; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0;net10.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
<PackageId>CareEvolution.Orchestrate</PackageId>
<Title>CareEvolution Orchestrate SDK</Title>
<Description>SDK for the Orchestrate API at api.careevolutionapi.com</Description>
<PackageProjectUrl>https://rosetta-api.docs.careevolution.com/</PackageProjectUrl>
<RepositoryUrl>https://github.com/CareEvolution/OrchestrateSDK</RepositoryUrl>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<Authors>CareEvolution</Authors>
<Version>0.0.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CareEvolution.Fhir.Core" Version="1.11.0" />
<PackageReference
Include="Microsoft.Extensions.DependencyInjection.Abstractions"
Version="8.0.2"
/>
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.1" />
</ItemGroup>
</Project>
10 changes: 10 additions & 0 deletions dotnet/src/CareEvolution.Orchestrate/ClassifyConditionRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace CareEvolution.Orchestrate;

public sealed class ClassifyConditionRequest
{
public required string Code { get; set; }

public required string System { get; set; }

public string? Display { get; set; }
}
27 changes: 27 additions & 0 deletions dotnet/src/CareEvolution.Orchestrate/ClassifyConditionResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Text.Json.Serialization;

namespace CareEvolution.Orchestrate;

public sealed class ClassifyConditionResponse
{
[JsonPropertyName("ccsrCatgory")]
public CodeableConcept? CcsrCategory { get; set; }

public Coding? CcsrDefaultInpatient { get; set; }

public Coding? CcsrDefaultOutpatient { get; set; }

public bool CciChronic { get; set; }

public bool CciAcute { get; set; }

public CodeableConcept? HccCategory { get; set; }

public bool Behavioral { get; set; }

public bool Substance { get; set; }

public bool SocialDeterminant { get; set; }

public string? Covid19Condition { get; set; }
}
10 changes: 10 additions & 0 deletions dotnet/src/CareEvolution.Orchestrate/ClassifyMedicationRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace CareEvolution.Orchestrate;

public sealed class ClassifyMedicationRequest
{
public required string Code { get; set; }

public required string System { get; set; }

public string? Display { get; set; }
}
Loading
Loading