API & SDKs
Programmatic management of your StrongDM organization. Covers API authentication, all four SDKs (Python, Go, Java, Ruby), CLI admin commands, and common automation patterns.
API Architecture
The StrongDM API is built on gRPC with a request signature model inspired by AWS V4 signing. You don't use bearer tokens alone -- every request is cryptographically signed, which means the secret key never travels over the wire. This protects against replay attacks and message tampering.
You interact with the API exclusively through one of the four official SDKs. There's no REST endpoint to hit directly. The SDKs handle all the gRPC plumbing, request signing, and pagination.
What You Can Do
Domain Objects
The API is organized around domain objects that map to StrongDM concepts. Each has standard CRUD operations (Create, Read, Update, Delete) plus List with filtering.
| Domain Object | What It Represents |
|---|---|
Accounts | Users and service accounts |
AccountAttachments | User-to-role assignments |
Resources | All resource types (databases, servers, clusters, etc.) |
Roles | Named collections of access rules |
RoleAccessRules | Static or dynamic access rules on roles |
Nodes | Gateways and relays |
SecretStores | Secret store integrations |
AccountsHistory | Change history for accounts (Enterprise: 13 months; Standard: 30 days) |
ResourcesHistory | Change history for resources |
Activities | Admin and user activity logs |
API Keys
Every SDK interaction requires an API key pair: an access key (hex string like auth-0123abcd) and a secret key (Base64 string). The access key identifies the request; the secret key signs it.
Creating API Keys
-
Open the Admin UIGo to Principals > Tokens.
-
Add API KeyClick Add API key. Give it a descriptive name. Set an expiration date. Choose permissions (minimum: the CRUD operations your automation needs).
-
Copy both keysCopy the access key and secret key immediately. The secret is shown only once.
API keys remain usable even if the user who created them is suspended. When suspending a user, the Admin UI will ask if their API keys should be deleted. Credential rotation is not currently available -- if a key is compromised, delete it and create a new one.
Best Practices
- Use environment variables (
SDM_API_ACCESS_KEYandSDM_API_SECRET_KEY) rather than hardcoding keys. - Scope permissions to the minimum required for your automation.
- Set expiration dates. Don't create keys that live forever.
- Create separate keys for separate automation systems so you can revoke individually.
SDK Setup & Usage
All four SDKs use semantic versioning with no compatibility guarantee between major versions. Pin your dependency to the major version you're on.
Installation
pip install strongdmConnect and List Users
import os
import strongdm
client = strongdm.Client(
os.getenv("SDM_API_ACCESS_KEY"),
os.getenv("SDM_API_SECRET_KEY"),
)
# List all accounts
for account in client.accounts.list(""):
print(account)Create a User
import os
import strongdm
client = strongdm.Client(
os.getenv("SDM_API_ACCESS_KEY"),
os.getenv("SDM_API_SECRET_KEY"),
)
user = strongdm.User(
first_name="Jane",
last_name="Doe",
email="[email protected]",
)
response = client.accounts.create(user)
print(f"Created user: {response.account.id}")Create a Resource
import os
import strongdm
client = strongdm.Client(
os.getenv("SDM_API_ACCESS_KEY"),
os.getenv("SDM_API_SECRET_KEY"),
)
postgres = strongdm.Postgres(
name="prod-postgres",
hostname="pg.internal.example.com",
port=5432,
database="production",
username="sdm_user",
password="secret",
tags={"env": "production", "team": "platform"},
)
response = client.resources.create(postgres)
print(f"Created resource: {response.resource.id}")Grant Access (Role + Attachment)
import os
import strongdm
client = strongdm.Client(
os.getenv("SDM_API_ACCESS_KEY"),
os.getenv("SDM_API_SECRET_KEY"),
)
# Create a role
role = strongdm.Role(name="SRE Team")
role_resp = client.roles.create(role)
role_id = role_resp.role.id
# Add a dynamic access rule (all production resources)
rule = strongdm.AccessRule(
tags={"env": "production"},
)
client.role_access_rules.create(strongdm.RoleAccessRule(
role_id=role_id,
access_rules=[rule],
))
# Attach a user to the role
attachment = strongdm.AccountAttachment(
account_id="a-0123456789",
role_id=role_id,
)
client.account_attachments.create(attachment)SDK reference: strongdm.github.io/strongdm-sdk-python-docs
Installation
go get github.com/strongdm/strongdm-sdk-goConnect and List Users
package main
import (
"context"
"fmt"
"log"
"os"
"time"
sdm "github.com/strongdm/strongdm-sdk-go"
)
func main() {
accessKey := os.Getenv("SDM_API_ACCESS_KEY")
secretKey := os.Getenv("SDM_API_SECRET_KEY")
client, err := sdm.New(accessKey, secretKey)
if err != nil {
log.Fatal("failed to create client:", err)
}
ctx, cancel := context.WithTimeout(
context.Background(), 30*time.Second,
)
defer cancel()
// List all accounts
users, err := client.Accounts().List(ctx, "")
if err != nil {
log.Fatal("failed to list accounts:", err)
}
for users.Next() {
user := users.Value()
fmt.Println(user)
}
if err := users.Err(); err != nil {
log.Fatal("iteration error:", err)
}
}Filtering
// Only return users named "Alice"
users, err := client.Accounts().List(ctx, "firstname:Alice")SDK reference: pkg.go.dev/github.com/strongdm/strongdm-sdk-go
Installation (Maven)
<dependency>
<groupId>com.strongdm</groupId>
<artifactId>strongdm-sdk-java</artifactId>
<version>LATEST</version>
</dependency>Connect and List Users
import com.strongdm.api.*;
public class ListUsers {
public static void main(String[] args)
throws Exception {
Client client = new Client(
System.getenv("SDM_API_ACCESS_KEY"),
System.getenv("SDM_API_SECRET_KEY")
);
Iterable<Account> accounts =
client.accounts().list("");
for (Account account : accounts) {
System.out.println(account);
}
}
}SDK reference: github.com/strongdm/strongdm-sdk-java
Installation
gem install strongdmConnect and List Users
require "strongdm"
client = SDM::Client.new(
ENV["SDM_API_ACCESS_KEY"],
ENV["SDM_API_SECRET_KEY"],
)
users = client.accounts.list("")
users.each do |user|
p user
endSDK reference: github.com/strongdm/strongdm-sdk-ruby
Pagination
When a List operation returns many results, the SDK handles pagination automatically. In Ruby and Python, the result is an iterator you loop over. In Go, you call Next() / Value() explicitly. You don't need to manually manage page tokens.
History and Audit Queries
History domain objects (like AccountsHistory) let you see what changed over time -- not just the current state. You specify a time range and get back a record of all changes.
CLI Admin Reference
The sdm CLI lets you manage StrongDM with your user credentials (after sdm login). The sdm admin subcommands cover the same operations as the API, useful for scripting and quick lookups.
Authentication
# Log in (opens browser for SSO if configured)
sdm login
# Log out
sdm logout
# Check status
sdm statusResource Management
# List all resources (all types)
sdm admin resources list
# List with extended detail
sdm admin resources list -e
# JSON output (for piping to jq)
sdm admin resources list --json
# Filter by tag
sdm admin resources list --filter "tag:env=production"
# List only datasources
sdm admin datasources list -e
# List only servers
sdm admin servers list -e
# Add an SSH server
sdm admin ssh create \
--name "web-server-01" \
--hostname 10.0.1.50 \
--port 22 \
--username ubuntu \
--tags "env=production,role=web"
# Delete a resource
sdm admin resources delete rs-0123456789abcdefUser & Service Account Management
# List all users
sdm admin users list
# List service accounts
sdm admin services list
# Create a service account
sdm admin services create --name "ci-deploy-bot"
# Suspend a user
sdm admin users suspend a-0123456789abcdef
# Assign a user to a role
sdm admin users assign --role "SRE Team" --user "[email protected]"Role & Access Management
# List roles
sdm admin roles list
# Create a role
sdm admin roles create --name "Database Team"
# List healthchecks for all nodes/resources
sdm admin healthchecks listAudit Log Export
# Export activities from a start date (CSV)
sdm audit activities --from "2026-01-01"
# Export as JSON
sdm audit activities --from "2026-01-01" -j
# Export to file
sdm audit activities --from "2026-01-01" -o activities.csv
# Export connection queries
sdm audit queries --from "2026-01-01" -jUseful Flags
| Flag | What It Does |
|---|---|
-e, --extended | Show detailed information for each item |
--json, -j | Output as JSON (great for piping to jq) |
--filter | Filter results (e.g., field:name, tag:key=value) |
--timeout | Set time limit for the command |
-h, --help | Help text for any command |
Full CLI Command Tree
sdm admin subcommands
├── datasources # list, add, clone, update, delete
├── servers # list, add, clone, update, delete
├── clusters # list, add, clone, update, delete
├── clouds # list, add, clone, update, delete
├── websites # list, add, clone, update, delete
├── resources # list, delete (all types)
├── nodes # list, create, delete
├── users # list, create, suspend, assign
├── services # list, add, suspend, rotate, grant
├── roles # list, create, delete
├── tokens # list, create, delete (API keys)
├── secretstores # list, create, update, delete
├── secretengines # list, create, update, delete
├── policies # list, create, update, delete
├── ports # list, override
├── healthchecks # list, run
├── identities # list, manage aliases
├── organization # settings
└── workflows # approval workflows
Common Operations by Task
Side-by-side reference for common tasks across Python SDK, CLI, and Terraform.
| Task | Python SDK | CLI |
|---|---|---|
| List all resources | client.resources.list("") |
sdm admin resources list |
| Create a user | client.accounts.create(User(...)) |
sdm admin users create ... |
| Suspend a user | client.accounts.delete(id) |
sdm admin users suspend <id> |
| Create a role | client.roles.create(Role(...)) |
sdm admin roles create --name "..." |
| Attach user to role | client.account_attachments.create(...) |
sdm admin users assign --role ... --user ... |
| Export audit logs | client.activities.list(...) |
sdm audit activities --from ... |
Automation Patterns
User Lifecycle Automation
Sync users from your IdP, auto-assign roles based on attributes, and clean up on departure.
import os
import strongdm
client = strongdm.Client(
os.getenv("SDM_API_ACCESS_KEY"),
os.getenv("SDM_API_SECRET_KEY"),
)
# Find all users in the "engineering" role
eng_role = None
for role in client.roles.list(""):
if role.name == "Engineering":
eng_role = role
break
# List current members
current = set()
for att in client.account_attachments.list(""):
if att.role_id == eng_role.id:
current.add(att.account_id)
print(f"Engineering role has {len(current)} members")Bulk Resource Onboarding
import os
import strongdm
client = strongdm.Client(
os.getenv("SDM_API_ACCESS_KEY"),
os.getenv("SDM_API_SECRET_KEY"),
)
databases = [
{"name": "prod-pg-01", "host": "pg1.internal", "db": "app"},
{"name": "prod-pg-02", "host": "pg2.internal", "db": "analytics"},
{"name": "staging-pg", "host": "pg-staging.internal", "db": "staging"},
]
for db in databases:
resource = strongdm.Postgres(
name=db["name"],
hostname=db["host"],
port=5432,
database=db["db"],
username="sdm_user",
password=os.getenv("DB_PASSWORD"),
tags={"env": "production", "team": "data"},
)
resp = client.resources.create(resource)
print(f"Created: {resp.resource.name} ({resp.resource.id})")Audit Log Export to SIEM
# Export last 24 hours of activities as JSON, pipe to your SIEM
sdm audit activities --from "$(date -d '24 hours ago' +%Y-%m-%d)" -j | \
curl -X POST https://siem.example.com/api/ingest \
-H "Content-Type: application/json" -d @-CI/CD: Dynamic Resource Registration
#!/bin/bash
# Called after Terraform creates a new RDS instance
# Registers it with StrongDM and tags it for auto-access
export SDM_API_ACCESS_KEY="$SDM_KEY"
export SDM_API_SECRET_KEY="$SDM_SECRET"
sdm admin datasources create postgres \
--name "$RDS_IDENTIFIER" \
--hostname "$RDS_ENDPOINT" \
--port 5432 \
--database "$DB_NAME" \
--username "$DB_USER" \
--password "$DB_PASS" \
--tags "env=production,team=platform,managed-by=ci"Tag resources consistently from CI/CD. If your roles use dynamic access rules based on tags, newly registered resources are automatically accessible to the right teams without any additional StrongDM configuration.
SCIM Integration
StrongDM supports SCIM 2.0 for automated user provisioning and deprovisioning. This is separate from the SDK API and is typically configured through your IdP (Okta, Entra, OneLogin, JumpCloud, or a generic SCIM client).
SCIM handles user sync and group-to-role mapping, so you don't need to write SDK code for basic provisioning if your IdP supports SCIM. Use the SDK/API for operations beyond what SCIM covers, like resource management, access rules, and audit queries.
Quick Reference
| SDK | Install | GitHub |
|---|---|---|
| Python | pip install strongdm | strongdm-sdk-python |
| Go | go get github.com/strongdm/strongdm-sdk-go | strongdm-sdk-go |
| Java | Maven: com.strongdm:strongdm-sdk-java | strongdm-sdk-java |
| Ruby | gem install strongdm | strongdm-sdk-ruby |
Content sourced from docs.strongdm.com and the StrongDM SDK repositories on GitHub, March 2026. For the latest SDK versions and full API reference, see the individual SDK docs linked above.