Skip to main content
Version: Preview

SDK

The Marmot SDK is a typed client for the REST API, available in Python, Go and TypeScript. Authentication resolves automatically from environment variables, cached OAuth tokens or workload identity.

Install

pip install marmot-sdk

Requires Python 3.10+. Package name is marmot-sdk, import name is marmot.

Authenticate

Every SDK resolves credentials from the same priority chain, so the same code runs locally, in CI and in production without branching on environment:

  1. Explicit arguments. api_key / token passed to connect() or NewClient().
  2. Environment variables. MARMOT_API_KEY, MARMOT_TOKEN, MARMOT_HOST, MARMOT_CONTEXT.
  3. Cached OAuth token. Written to ~/.config/marmot/credentials.json by marmot login.
  4. Workload identity. GitHub Actions OIDC, GCP metadata or a Kubernetes service-account token. No API key needed.

If no credential resolves, the SDK raises an AuthError so misconfiguration fails fast.

Log in for local use:

marmot login http://localhost:5173

Then construct a client:

import marmot

# Resolves from the chain
client = marmot.connect()

# Or pass an API key explicitly
client = marmot.connect(base_url="https://marmot.example.com", api_key="...")

# Context manager closes the underlying httpx client on exit
with marmot.connect() as client:
me = client.users.me()

The following sections all assume client (and ctx for Go) is already constructed as shown above.

client.search(query) is the unified search across assets, glossary terms, teams and data products. Returns a typed SearchResponse with facets, results and pagination.

import marmot

client = marmot.connect()

results = client.search("orders", types=["Table", "Topic"], limit=20)
for hit in results.results:
print(hit.name, hit.metadata.get("mrn"))

Marmot accepts both free-text queries and a structured query language (@type: "Table" AND @provider: "postgres"). See the Query Language guide for the full grammar.

Assets

Every catalog entry is an Asset. The Assets resource covers CRUD, lookup by natural key, search, summary aggregates and tag management.

Fetch by ID

import marmot

client = marmot.connect()

asset = client.assets.get("01HX...")
print(asset.name, asset.mrn)

Lookup by natural key

When you know an asset by (type, service, name) but not its ID, lookup resolves it. find does the same but returns nil / None instead of raising on a miss.

import marmot

client = marmot.connect()

asset = client.assets.lookup(type="Table", service="postgres", name="orders")
maybe = client.assets.find(type="Table", service="postgres", name="orders") # None on 404

Search and summary

import marmot

client = marmot.connect()

hits = client.assets.search(
query="customer",
types=["Table"],
providers=["postgres"],
tags=["pii"],
limit=50,
)
summary = client.assets.summary() # totals by type, provider, tag

Create, update, delete

import marmot

client = marmot.connect()

created = client.assets.create({
"name": "orders",
"type": "Table",
"providers": ["postgres"],
"metadata": {"owner": "data-eng"},
})

updated = client.assets.update(created.id, {"description": "Customer orders"})
client.assets.delete(created.id)

Tag management

import marmot

client = marmot.connect()

client.assets.add_tag(asset_id, "pii")
client.assets.remove_tag(asset_id, "pii")

Lineage

Lineage edges identify endpoints by MRN (<type>://<service>/<name>). Read the graph from any node; write one edge or many at a time.

Read the graph

import marmot

client = marmot.connect()

graph = client.lineage.get(asset_id, direction="both", limit=50)
upstream = client.lineage.upstream(asset_id, limit=10)

Write edges

Prefer /lineage/direct and /lineage/batch for new integrations. They accept simple (source, target) pairs and de-duplicate server-side.

import marmot

client = marmot.connect()

# Single edge
client.lineage.write(
source="postgres://prod/sales/orders",
target="kafka://prod/orders.events",
)

# Batched: one HTTP call, many edges
client.lineage.batch([
("postgres://prod/sales/orders", "kafka://prod/orders.events"),
("kafka://prod/orders.events", "s3://prod/orders-archive"),
])

Leave Type empty (DIRECT is the default) for code-derived edges; set it explicitly ("writes", "AGENT_LOOKUP", …) when you want to distinguish causes in the lineage graph.

Glossary

Business glossary terms with definitions, descriptions and hierarchies via parent_term_id.

import marmot

client = marmot.connect()

page = client.glossary.list(limit=50)
hits = client.glossary.search(query="customer")

term = client.glossary.create(
name="PII",
definition="Personally Identifiable Information",
description="Data that can identify an individual.",
)

client.glossary.update(term.id, name="Personally Identifiable Information")
client.glossary.delete(term.id)

Users & Teams

import marmot

client = marmot.connect()

me = client.users.me()
user = client.users.get(user_id)
users = client.users.list(active=True, limit=100)

teams = client.teams.list()
team = client.teams.get(team_id)
members = client.teams.members(team_id)

API Keys

Manage personal API keys for the authenticated user. The full key token is only readable from the create response, so store it immediately.

import marmot

client = marmot.connect()

keys = client.api_keys.list()
created = client.api_keys.create(name="ci-deploy", expires_in_days=30)
print(created.key) # only readable here
client.api_keys.delete(created.id)

Runs

Read pipeline-ingestion run history. Useful when wiring up alerts on failed ingests or audit dashboards.

import marmot

client = marmot.connect()

recent = client.runs.list(statuses="failed,running", limit=20)
run = client.runs.get(run_id)
entities = client.runs.entities(run_id, status="failed")

Metrics

Catalog usage and breakdown metrics. top_assets and top_queries take an inclusive [start, end] window of RFC3339 timestamps.

import marmot

client = marmot.connect()

total = client.metrics.total_assets()
by_type = client.metrics.assets_by_type()
by_provider = client.metrics.assets_by_provider()

top = client.metrics.top_assets(
start="2025-01-01T00:00:00Z",
end="2025-02-01T00:00:00Z",
limit=10,
)
queries = client.metrics.top_queries(
start="2025-01-01T00:00:00Z",
end="2025-02-01T00:00:00Z",
limit=10,
)

Owners

Search the catalog for asset owners (users and teams).

import marmot

client = marmot.connect()

hits = client.owners.search("alice", limit=10)

Admin

Trigger or poll a full search reindex. Requires admin permissions.

import marmot

client = marmot.connect()

accepted = client.admin.reindex()
status = client.admin.reindex_status()
print(status.running, status.es_configured)

Building an agent?

Marmot for Agents builds on the SDK to give LLM agents the catalog as tools and writes their lineage automatically.

Read the guide