Skip to main content

Overview

Some SDK functionality — including policy management and authorization decisions — is provided through a platform service client rather than through the core SDK. This page explains the difference and when you'll use each.

Core SDK vs. Platform Service Client

Core SDKPlatform Service Client
What it doesWraps and unwraps TDF-protected dataManages platform resources (policy, keys, authorization)
Calls platformSome operations (e.g. key unwrap, service discovery)Always — all methods are remote gRPC calls
ExamplesCreateTdf, LoadTdfGetNamespace, GetDecision, ListKeyAccessServers

This is the same pattern used by cloud provider SDKs — you instantiate a typed client once (analogous to new S3Client() in AWS), then call methods on it to manage remote resources.

gRPC is a high-performance open-source remote procedure call framework. It uses HTTP/2 for transport and Protocol Buffers for serialization, enabling strongly-typed service contracts across languages.

Initializing the SDK client

JavaScript examples use client credentials for simplicity

The JavaScript SDK is designed for browser applications. The examples on this page use clientCredentialsTokenProvider because it's self-contained and easy to follow, but it requires a client secret and must not be used in browser code.

In production browser apps, complete an OIDC login flow to obtain a refresh token, then use refreshTokenProvider(). See the Authentication Decision Guide for help choosing the right method.

import (
"github.com/opentdf/platform/sdk"
// Plus the service-specific package for each call, e.g.:
"github.com/opentdf/platform/protocol/go/policy/namespaces"
authorization "github.com/opentdf/platform/protocol/go/authorization/v2"
)

client, err := sdk.New("http://localhost:8080",
sdk.WithClientCredentials("client-id", "client-secret", nil),
)
if err != nil {
log.Fatal(err)
}
defer client.Close()

// Platform services are accessed directly on the client, e.g.:
resp, err := client.Namespaces.ListNamespaces(ctx, &namespaces.ListNamespacesRequest{})

decision, err := client.AuthorizationV2.GetDecision(ctx, &authorization.GetDecisionRequest{
// ...
})

Response Objects

All platform API calls return protobuf response objects. The way you access fields differs by language: Go uses generated getter methods prefixed with Get, Java uses standard getters, and JavaScript uses direct property access with optional chaining.

GetAttributeValue — accessing a policy attribute value:

resp, err := client.Attributes.GetAttributeValue(ctx, req)
v := resp.GetValue()
v.GetValue() // "confidential"
v.GetFqn() // "https://example.com/attr/classification/value/confidential"
v.GetId() // "a1b2c3d4-..."

ListAttributeValues — iterating over a list response:

resp, err := client.Attributes.ListAttributeValues(ctx, req)
for _, v := range resp.GetValues() {
v.GetValue() // "confidential"
v.GetFqn() // "https://example.com/attr/classification/value/confidential"
}

GetDecision — accessing an authorization decision:

resp, err := client.AuthorizationV2.GetDecision(ctx, req)
d := resp.GetDecision()
d.GetDecision() // DECISION_PERMIT or DECISION_DENY
d.GetRequiredObligations() // []string of obligation value FQNs

GetEntitlements — accessing entity entitlements:

resp, err := client.AuthorizationV2.GetEntitlements(ctx, req)
for _, e := range resp.GetEntitlements() {
e.GetActionsPerAttributeValueFqn() // map of FQN → permitted actions
}

This pattern applies to all platform objects. Each SDK page includes type reference tables listing the available fields.