Phenostore SDKs
Use the Go or Python SDK to work with JSON resources and manage access tokens automatically. Phenostore is in beta; request access for your API URL, tenant, store, and client credentials.
Install
Choose your language and install the SDK in your Go module or Python virtual environment:
| Go | Python | |
|---|---|---|
| Runtime | Go 1.26.0 or later | Python 3.11 or later |
| Install | go get github.com/phenoml/phenostore-sdk-go | python -m pip install phenostore-sdk-python |
| Import | github.com/phenoml/phenostore-sdk-go/phenostore | phenostore |
| Resource bodies | json.RawMessage | Plain dictionaries |
The Python package is published on PyPI.
Create and read a Patient
Set PHENOSTORE_BASE_URL, TENANT_ID, STORE_ID, PHENOSTORE_CLIENT_ID, and
PHENOSTORE_CLIENT_SECRET with your onboarding values, as described in the
REST quickstart. Use the supplied API origin
as the base URL, without a trailing slash or tenant/store suffix. Keep these
credentials on the server and out of source control.
Both programs create the same synthetic Patient as the REST quickstart, extract its server-assigned ID, and read it back. The Python example also searches by identifier. Choose a language to view its complete program:
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"os"
"time"
"github.com/phenoml/phenostore-sdk-go/phenostore"
)
func requiredEnv(name string) string {
value := os.Getenv(name)
if value == "" {
log.Fatalf("Set %s before running this example", name)
}
return value
}
func main() {
client, err := phenostore.NewClient(
requiredEnv("PHENOSTORE_BASE_URL"),
requiredEnv("PHENOSTORE_CLIENT_ID"),
requiredEnv("PHENOSTORE_CLIENT_SECRET"),
requiredEnv("TENANT_ID"),
requiredEnv("STORE_ID"),
)
if err != nil {
log.Fatal("Could not configure the Phenostore client")
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
body := json.RawMessage(`{
"resourceType": "Patient",
"identifier": [
{"system": "https://example.com/patients", "value": "beta-demo-001"}
],
"name": [{"family": "Example", "given": ["Beta"]}]
}`)
created, err := client.CreateResource(ctx, "Patient", body, nil)
if err != nil {
log.Fatal("Create failed; check credentials, permissions, and validation settings")
}
var patient struct {
ID string `json:"id"`
}
if err := json.Unmarshal(created, &patient); err != nil || patient.ID == "" {
log.Fatal("Create response did not include a valid resource ID")
}
_, err = client.ReadResource(ctx, "Patient", patient.ID)
if phenostore.IsNotFound(err) {
log.Fatal("The created Patient was not found")
}
if err != nil {
log.Fatal("Read failed; check credentials and store permissions")
}
fmt.Println("Synthetic Patient created and read successfully")
}
| Go | Python | |
|---|---|---|
| Save as | main.go | main.py |
| Prepare dependencies | go mod tidy | Included in the installation above |
| Run | go run . | python main.py |
Each run creates another resource. The programs print a success message rather
than resource payloads or raw error bodies. Go uses a context timeout; Python
configures HTTP timeouts and closes pooled connections with a with block.
Authentication and errors
The SDKs acquire tokens on demand at /oauth/token and refresh them
automatically. Request only scopes granted to your client during onboarding.
| Go | Python | |
|---|---|---|
| Request scopes | phenostore.WithScopes(...) option to NewClient | scopes=[...] argument to Client or AsyncClient |
| FHIR API errors | *phenostore.OperationOutcomeError with StatusCode and Body | OperationOutcomeError with status_code, body, and parsed outcome when available |
| Not-found helper | phenostore.IsNotFound(err) | is_not_found(error) |
| Generated API | client.Inner() | client.inner |
In Go, use errors.As to inspect an OperationOutcome error's status.
Authentication and transport failures can return other error types.
In Python, token failures raise AuthenticationError, invalid JSON or
non-object responses raise InvalidResponseError, and HTTPX network/timeout
exceptions propagate to the caller. Python requests are not retried
automatically. Avoid logging unsanitized error bodies, diagnostics, or resource
documents in either language.
For asynchronous Python applications, use AsyncClient in an async with
block and await the same six convenience methods, such as
await client.read_resource("Patient", patient_id). Keep each async client
within one event loop. When managing Python clients manually, call close()
on Client or await aclose() on AsyncClient.
Convenience methods
| Operation | Go | Python |
|---|---|---|
| Read by type and ID | ReadResource | read_resource |
| Create | CreateResource | create_resource |
| Update or upsert | UpdateResource | update_resource |
| Delete | DeleteResource | delete_resource |
| Search | SearchResources | search_resources |
| Transaction or batch Bundle | ProcessBundle | process_bundle |
Python accepts resource-specific search filters such as identifier, as well
as control parameters such as _count. List values or a sequence of name/value
pairs support repeated parameters. The generated Go gen.SearchResourcesParams
exposes search control parameters rather than arbitrary resource-specific
filters; see the REST quickstart for filtering
by identifier.
Search results are searchset Bundles with resources in entry[].resource.
Pagination is explicit: use returned Bundle links or cursors in subsequent
requests. Bundle.total is not always present. Inspect your store's authenticated
/metadata response for its supported resource types, interactions, and filters.
Python supports if_none_exist on create_resource for conditional creation
and if_match on update_resource for version checks. The Go create/update
methods accept generated parameter structs for these headers.
Further reference
| Go | Python | |
|---|---|---|
| Repository | Go SDK | Python SDK |
| Complete example | Go example | Python example |
Use the generated API for operations beyond the convenience methods, such as history and metadata. In Python, match synchronous or asynchronous generated functions to the corresponding client; the repository describes their response and error handling.