- Fixed APIClient.wrapped() doc to use job_function instead of job - Updated WRAPPERS.md parameter tables: - update_post(): Corrected all parameters (post_text, post_path, parent_path, post_key, blur_label, card_url, collaborative) - create_comment(): Made parent_path optional, added comment_text requirement, clarified post_slug/post_key alternatives # Conflicts: # docs/WRAPPERS.md |
||
|---|---|---|
| docs | ||
| src/trustcafeapiwrapper | ||
| tests | ||
| .gitignore | ||
| .gitlab-ci.yml | ||
| .python-version | ||
| development.md | ||
| documentation.md | ||
| pyproject.toml | ||
| README.md | ||
| setup.py | ||
| testing.py | ||
| unittests.py | ||
| uv.lock | ||
| venv.bat | ||
TrustCafé API Wrapper
A Python wrapper for the TrustCafé API, providing a convenient interface to interact with TrustCafé features programmatically.
Table of Contents
- Prerequisites
- Installation
- Quick Start
- Authentication
- API Reference
- Custom Requests
- Environment Setup
- Debug Mode
- Examples
- Development
- Testing
Prerequisites
Before you begin, ensure you have:
- Python 3.11 or higher installed
- API Client ID and Secret from TrustCafé
- python-dotenv (for
.envfile support) or ability to set environment variables
Getting API Credentials
-
Visit your TrustCafé account page:
-
Click "Create new client credentials key pair"
-
Choose the scopes you need (or select all for full access)
-
Click "Save"
-
Copy the client_id and client_secret to your environment:
- The secret cannot be retrieved later — make sure to save it securely
- Do not commit these credentials to version control
Installation
# Using pip
pip install trustcafeapiwrapper
# Using uv (recommended)
uv add trustcafeapiwrapper
Quick Start
The simplest way to get started:
import trustcafeapiwrapper
import os
# Initialize the API client
API = trustcafeapiwrapper.APIClient(
client_id=os.getenv("TRUSTCAFE_CLIENT_ID"),
client_secret=os.getenv("TRUSTCAFE_CLIENT_SECRET"),
env="alpha", # Options: "alpha" or "production"
debug=False
)
# Authenticate and get user profile
API.handle_token()
profile = API.run_job('userprofile.get', "your-username")
print(profile)
Authentication
The API wrapper handles OAuth2 client-credentials authentication automatically.
Automatic Token Management
API.handle_token()
What it does:
- Checks for an existing token file (
token_data_{env}.json) - If found, verifies if the token is still valid
- If expired or not found, obtains a new access token (~3 month duration)
- Saves the token to a local file for future requests
Manual Token Management
For more control over token storage:
def getMyToken():
# Retrieve token from your custom storage (database, file, etc.)
return {
"access_token": "***",
"access_token_timeout": 9999999999 # Unix timestamp
}
def saveMyToken(token_data):
# Save to your preferred storage
with open("my_token_cache.json", "w") as f:
json.dump(token_data, f)
return True
# Set the token manually or pass to initialize
API = APIClient(
client_id=os.getenv("client_id"),
client_secret=os.getenv("client_secret"),
env="production",
debug=False
)
# Use existing token or get a new one
if not API.is_token_valid():
saveMyToken(API.sign_in())
Token Validation
if API.is_token_valid():
print("Token is valid")
else:
API.handle_token() # Get a new token
Environment Setup
The wrapper supports two environments:
| Environment | URL | Purpose |
|---|---|---|
alpha |
alpha.wts2.net |
Development/staging environment |
production |
trustcafe.io |
Production environment |
# Alpha environment (default)
API = APIClient(
client_id="your-client-id",
client_secret="your-client-secret",
env="alpha",
debug=False
)
# Production environment
API = APIClient(
client_id="your-client-id",
client_secret="your-client-secret",
env="production",
debug=False
)
# Change environment dynamically
API.set_environment("production")
API Reference
Jobs
Jobs are pre-built functions that map to specific API endpoints. They return the raw response from the API.
Post Operations
# Get a specific post
post = API.run_job('post.get', "post-slug-or-id")
# Create a post
post = API.run_job('post.create', {
"postText": "This is a test post",
"parent": {
"pk": "maintrunk#maintrunk",
"sk": "maintrunk#maintrunk"
}
})
# List all posts
posts = API.run_job('post.listall')
# List public posts
public_posts = API.run_job('post.listpublic')
# List posts by a specific branch
branch_posts = API.run_job('post.listbybranch', "branch-name")
# List posts by a user profile
user_posts = API.run_job('post.listbyuserprofile', "username")
# Update a post
updated_post = API.run_job('post.update', {
"pk": "post-id",
"sk": "post-id",
"newPostText": "Updated text"
})
# Delete a post
deleted = API.run_job('post.listremoved', "post-id")
Comment Operations
# Create a comment
comment = API.run_job('comment.create', {
"commentText": "This is a comment",
"parent": {
"pk": "post-id",
"sk": "post-id"
}
})
# Get comments by post ID
comments = API.run_job('comment.listtbypostid', "post-id")
User Profile Operations
# Get user profile
profile = API.run_job('userprofile.get', "username")
Follow Operations
# Follow a user
followed = API.run_job('follow.follow', {
"isFollowing": true,
"parent": {
"pk": "userprofile#username",
"sk": "userprofile#username"
},
"followType": "userprofile",
"parentSlug": "username"
})
Vote Operations
# Cast a vote
voted = API.run_job('vote.votecast', {
"parent": {
"pk": "post-id",
"sk": "post-id",
"slug": "post-slug",
"entity": "post"
},
"vote": "up" # or "down"
})
Reaction Operations
# React to something (post, comment, etc.)
reactions = API.run_job('reaction.reacttosomething', {
"parent": {
"pk": "post-id",
"sk": "post-id"
},
"reaction": "like" # various types supported
})
# Get reactions by parent
post_reactions = API.run_job('reaction.getbyparent', "parent-id")
# List reactions
reactions_list = API.run_job('reaction.listbyparent', "parent-id")
Notification Operations
# List all notifications
notifications = API.run_job('notification.listnotifications')
# Mark all as read
API.run_job('notification.markallasread')
Trust Operations
# Create or update trust relationship
trust = API.run_job('trust.createorupdate', {
"pk": "trust_id",
"sk": "trust_id",
"trustType": "positive"
})
# List trust by user initialization
trusts = API.run_job('trust.listbyusersinit', "username")
# List trust by user has
trusts = API.run_job('trust.listbyuserhas', "username")
Branch Operations
# Get a specific branch
branch = API.run_job('branch.get', "branch-name")
# List branches (all branches with pagination)
branches = API.run_job('branch.listbyname')
Feed Operations
# Get café feed
feed = API.run_job('feed.cafefeed')
# Get following feed
following_feed = API.run_job('feed.followingfeed')
Block Operations
# Block a user (function exists but needs implementation)
# TODO: Add job function for block operations
Mute Operations
# Mute functionality (to be added)
# TODO: Add job function for mute operations
Wrappers
Wrappers are high-level functions that simplify common operations by handling payload preparation and job execution automatically.
Using a Wrapper
API.handle_token()
# Create a post with a wrapper (recommended for simplicity)
from trustcafeapiwrapper.wrappers.post.create_post import create_post
API.wrapped(create_post(
"This is a test post created via the wrapper.",
parent_path="/", # Root path (optional)
blur_label=None, # Optional blurring
card_url=None, # Optional card URL
collaborative=False # Optional collaboration flag
))
# Create a comment
from trustcafeapiwrapper.wrappers.comment.create_comment import create_comment
API.wrapped(create_comment(
"This is a comment",
parent_path="/" # Parent path (required)
))
About Wrappers:
- Wrappers simplify common operations
- They prepare the payload and job execution automatically
- More wrappers are being added for consistency
- For flexibility, use Jobs or Custom Requests
Note on APIClient.wrapped(): The method expects a wrapped_data dictionary with keys job_function and payload:
API.wrapped({
"job_function": "post.create",
"payload": {...}
})
Using run_job vs. Wrappers
| Feature | run_job |
Wrappers |
|---|---|---|
| Simplicity | Higher | Highest for common tasks |
| Flexibility | Maximum | Optimized for specific use cases |
| Discovery | Need to know job format | Self-documenting payloads |
| Customization | Full control | Pre-defined options |
Recommendation:
- Use Wrappers for common, well-documented operations
- Use Jobs when you need fine-grained control
- Use Custom Requests when neither fits your needs
Custom Requests
For operations not covered by jobs or wrappers, use the make_request method:
# Make a raw API request
response = API.make_request(
method="GET",
endpoint="content",
path="post/some-custom-path",
authenticate=True,
query_params={"param1": "value1"}
)
Parameters:
method(str): HTTP method - "GET", "POST", "PUT", "DELETE"endpoint(str): API endpoint - "content", "auth", "audrey", etc.path(str): API path after endpointauthenticate(bool): Whether to include authentication tokenquery_params(dict): Optional query parameters
Example - Custom Request:
# Get posts from a specific branch with filters
posts = API.make_request(
"GET",
"content",
"post/ref-subwiki/music",
query_params={"limit": 10, "offset": 0}
)
Debug Mode
Enable debug mode to see all API requests and responses:
API = APIClient(
client_id=os.getenv("client_id"),
client_secret=os.getenv("client_secret"),
env="production",
debug=True # Enable debug mode
)
# Now API calls will print request details
API.handle_token()
Examples
Example 1: Basic Post Creation
import trustcafeapiwrapper
import os
# Setup
API = trustcafeapiwrapper.APIClient(
client_id=os.getenv("TRUSTCAFE_CLIENT_ID"),
client_secret=os.getenv("TRUSTCAFE_CLIENT_SECRET"),
env="alpha",
debug=False
)
# Handle authentication
API.handle_token()
# Create a post in the music branch
from trustcafeapiwrapper.wrappers.post.create_post import create_post
API.wrapped(create_post(
"New music discussion post",
parent_path="/music",
blur_label=None,
card_url=None,
collaborative=False
))
Example 2: Following a User and Getting Their Profile
import trustcafeapiwrapper
import os
API = trustcafeapiwrapper.APIClient(
client_id=os.getenv("TRUSTCAFE_CLIENT_ID"),
client_secret=os.getenv("TRUSTCAFE_CLIENT_SECRET"),
env="production"
)
# Follow a user
follow = API.run_job('follow.follow', {
"isFollowing": true,
"parent": {
"pk": "userprofile#philosopher-jon",
"sk": "userprofile#philosopher-jon"
},
"followType": "userprofile",
"parentSlug": "philosopher-jon"
})
print(f"Followed user: {follow}")
# Get their profile
profile = API.run_job('userprofile.get', "philosopher-jon")
print(f"Profile data: {profile}")
Example 3: Managing Notifications
import trustcafeapiwrapper
import os
API = trustcafeapiwrapper.APIClient(
client_id=os.getenv("TRUSTCAFE_CLIENT_ID"),
client_secret=os.getenv("TRUSTCAFE_CLIENT_SECRET"),
env="production"
)
API.handle_token()
# Check for new notifications
notifications = API.run_job('notification.listnotifications')
print(f"Unread notifications: {notifications}")
# Mark all as read
API.run_job('notification.markallasread')
print("All notifications marked as read")
Example 4: Creating a Collaborative Post
import trustcafeapiwrapper
import os
API = trustcafeapiwrapper.APIClient(
client_id=os.getenv("TRUSTCAFE_CLIENT_ID"),
client_secret=os.getenv("TRUSTCAFE_CLIENT_SECRET"),
env="production"
)
API.handle_token()
# Create a collaborative post
from trustcafeapiwrapper.wrappers.post.create_post import create_post
API.wrapped(create_post(
"Research paper draft - collaborative editing",
parent_path="/research",
collaborative=True # Enables collaborative editing
))
Development
Project Structure
trustcafe-api-wrapper/
├── src/
│ └── trustcafeapiwrapper/
│ ├── apiclient.py # Core API client
│ ├── jobs/ # API job functions
│ │ ├── post/
│ │ ├── comment/
│ │ ├── userprofile/
│ │ ├── follow/
│ │ └── ... (all jobs)
│ ├── wrappers/ # High-level wrappers
│ │ ├── post/
│ │ ├── comment/
│ │ └── ...
│ └── utils/ # Helper functions
├── tests/ # Test files
├── README.md # This file
├── documentation.md # Basic documentation
├── development.md # Project notes
└── pyproject.toml # Project configuration
Adding New Jobs
- Create a new file in
src/trustcafeapiwrapper/jobs/ - Define a function matching the job name
- Export it from the module's
__init__.py - Document the parameters and return value
Example - Adding a Job:
# src/trustcafeapiwrapper/jobs/example/new_job.py
def my_new_job(API, param1: str, param2: int) -> dict:
"""
Create a new job function.
Args:
API: The APIClient instance
param1 (str): Description of parameter 1
param2 (int): Description of parameter 2
Returns:
dict: The API response
"""
response = API.make_request(
"POST",
"endpoint",
"path/to/resource",
data={"param1": param1, "param2": param2}
)
return response
Known Limitations
- Incomplete Jobs: Not all available API endpoints have wrapper functions yet
- Enums: Some enum types are not strictly typed
- Block Operations: Block functionality exists in backend but not yet exposed
- Mute Operations: Mute functionality pending implementation
Future Enhancements
- Complete coverage of all TrustCafé API endpoints
- Type hints for better IDE support
- Async support for better performance
- Comprehensive test suite
- Pydantic models for request/response validation
Testing
Run the test suite:
pytest
Or run specific tests:
# Test the API client
python -m pytest tests/apiclient.py
# Run all tests
python -m pytest tests/
License
[Depends on TrustCafé project license]
Support
For issues, questions, or contributions:
- TrustCafé Website
- GitLab Repository
- Contact the WikiTribune team
Version History
- 0.1.0.13 - Current version with ongoing development
Note: This wrapper is for internal WikiTribune/TrustCafé use. Public API endpoints are subject to change.