Skip to main content

Python SDK

The official Python SDK for the OfSelf API.

Installation

pip install ofself

Requirements:

  • Python 3.8+

Quick Start

from ofself import OfSelfClient

# Initialize the client with API key (for third-party apps)
client = OfSelfClient(api_key="your-api-key")

# Or with access token from login (for first-party apps)
# client = OfSelfClient(access_token="your-jwt-token")

# Create a node
node = client.nodes.create(
user_id="user-123",
title="My First Experience",
value="Hello, OfSelf!",
node_type="EXPERIENCE", # Use: EXPERIENCE, BELIEF, ENTITY, or GOAL
meaning_level="DATA", # Use: DATA, CONTEXT, or IDENTITY
graph_view="identity", # Required for nodes to appear in app.ofself.ai
tags=["Work"]
)

print(f"Created: {node['id']}")
access_token Limitations

When using access_token authentication, some SDK methods may return 401 errors. If you encounter this, use raw HTTP requests with Bearer token instead:

import requests

headers = {"Authorization": f"Bearer {access_token}"}
response = requests.post(
"https://api.ofself.ai/api/v1/nodes",
headers=headers,
json={
"title": "My Node",
"node_type": "EXPERIENCE",
"meaning_level": "DATA",
"graph_view": "identity"
}
)

Configuration

from ofself import OfSelfClient

client = OfSelfClient(
api_key="your-api-key",
base_url="https://api.ofself.ai/api/v1", # Default
timeout=30.0 # Request timeout in seconds
)

Environment Variables

# .env
OFSELF_API_KEY=ofs_tp_xxxxxxxxxxxx.yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
import os
from ofself import OfSelfClient

client = OfSelfClient(api_key=os.environ["OFSELF_API_KEY"])

Resources

Nodes

# Create (use semantic node types: EXPERIENCE, BELIEF, ENTITY, GOAL)
node = client.nodes.create(
user_id="user-123",
title="Team planning meeting",
value="Discussed Q2 roadmap...",
node_type="EXPERIENCE",
meaning_level="CONTEXT",
graph_view="identity", # Required to appear in app.ofself.ai
tag_ids=["tag_work"]
)

# List
result = client.nodes.list(
user_id="user-123",
node_type="EXPERIENCE",
page=1,
per_page=20
)

# Get
node = client.nodes.get(user_id="user-123", node_id="node_abc")

# Update
node = client.nodes.update(
user_id="user-123",
node_id="node_abc",
title="Updated Title"
)

# Delete
client.nodes.delete(user_id="user-123", node_id="node_abc")

# Vector search
results = client.nodes.vector_search(
user_id="user-123",
embedding=[0.1, 0.2, 0.3],
limit=10,
min_score=0.7,
graph_view="neutral",
)

Tags

# Create
tag = client.tags.create(
user_id="user-123",
name="Work",
color="#3B82F6"
)

# List
result = client.tags.list(user_id="user-123")

# Get nodes with tag
nodes = client.tags.get_nodes(user_id="user-123", tag_id="tag_work")

# Add tag to node
client.nodes.add_tag(user_id="user-123", node_id="node_abc", tag_id="tag_work")

Files

# Upload
file = client.files.upload(
user_id="user-123",
file="/path/to/document.pdf",
tag_ids=["tag_documents"]
)

# List
result = client.files.list(user_id="user-123")

# Download
content = client.files.download(user_id="user-123", file_id="file_abc")
with open("downloaded.pdf", "wb") as f:
f.write(content)

Proposals

Third-Party Authentication Required

The proposals endpoint requires third-party app authentication (API Key). It does not work with user JWT tokens. For first-party apps, create nodes directly instead.

# Create proposal (requires API key authentication)
proposal = client.proposals.create(
user_id="user-123",
title="Create experience from import",
type="CREATE_NODE",
canonical_data={
"entities": [{
"title": "Imported Experience",
"value": "Content",
"node_type": "EXPERIENCE",
"meaning_level": "DATA",
"graph_view": "identity"
}]
}
)

# List pending
result = client.proposals.list(user_id="user-123", status="pending")

# Approve (as user)
client.proposals.approve(user_id="user-123", proposal_id="prop_abc")

Graph

# Get snapshot for visualization
graph = client.graph.snapshot(user_id="user-123")

print(f"Nodes: {len(graph['nodes'])}")
print(f"Edges: {len(graph['edges'])}")

Follows (user connections)

Follows are JWT-only (user auth):

from ofself import OfSelfClient

client = OfSelfClient(access_token="your-jwt")

# Follow someone
client.follows.create(target_user_id="user-uuid", message="Hey!")

# Incoming requests (you are being followed)
incoming = client.follows.list_incoming(status="pending")

# Respond (accept + share)
client.follows.respond(
follow_id="follow-id",
action="accept",
share={"scope": "all"},
)

Error Handling

from ofself import OfSelfClient
from ofself.exceptions import (
OfSelfError,
AuthenticationError,
PermissionDenied,
NotFoundError,
ValidationError,
RateLimitError,
ServerError,
)

client = OfSelfClient(api_key="your-key")

try:
node = client.nodes.get(user_id="user-123", node_id="invalid")
except AuthenticationError:
print("Invalid API key")
except PermissionDenied:
print("User hasn't authorized your app")
except NotFoundError:
print("Node not found")
except ValidationError as e:
print(f"Validation failed: {e.errors}")
except RateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after}s")
except ServerError:
print("Server error - try again later")
except OfSelfError as e:
print(f"API error: {e}")

Context Manager

with OfSelfClient(api_key="your-key") as client:
nodes = client.nodes.list(user_id="user-123")
# Client is automatically closed

Type Hints

The SDK is fully typed. Use with IDE for autocomplete:

from ofself import OfSelfClient
from ofself.types import Node, Tag, Proposal

client = OfSelfClient(api_key="key")

# IDE knows return types
node: dict = client.nodes.create(...)

Pagination

# Iterate through all pages
page = 1
all_nodes = []

while True:
result = client.nodes.list(
user_id="user-123",
page=page,
per_page=100
)
all_nodes.extend(result['items'])

if not result['has_next']:
break
page += 1