trustcafe-api-wrapper/docs/WRAPPERS.md
BarnacleBoy a223bcb27a doc: audit pass — fix env= bug, params, pagination, missing wrappers, broken examples
- env= -> environment= across all docs (Pydantic silently ignores env=)
- Remove __version__ check (doesn't exist in module)
- Fix APIClient(debug=True) missing required client_id/secret
- Fix post.listremoved usage (takes no postId, just lists removed posts)
- Fix JS true/false -> Python True/False in code blocks
- Fix parameter names: branchName->branch_slug, username->user_slug, postId->post_id
- Add missing lastEvaluatedKey param docs for list jobs
- Note post.listpublic as unauthenticated endpoint
- Fix pagination examples (LastEvaluatedKey, not ExclusiveStartKey dict)
- Remove non-existent headers param from make_request example
- Fix branch.listbyname example (takes no name arg)
- Add 4 missing wrapper docs: follow, react, trust, votecast
- Fix broken internal links (case-sensitive filenames)
- Fix <environment>_handle_token template artifact
- Add CODE_BUGS.md documenting 4 code bugs found during audit
2026-04-18 22:58:33 +00:00

17 KiB

TrustCafé API Wrapped Functions Guide

This guide covers the high-level wrapper functions provided by the TrustCafé API wrapper. Wrappers simplify common operations by handling payload preparation and job execution automatically.

Table of Contents

Overview

What are Wrappers?

Wrappers are pre-built functions that encapsulate common TrustCafé API operations. They:

  • Simplify usage: Less boilerplate code
  • Handle payload preparation: Automatically structure requests
  • Prevent errors: Built-in validation and defaults
  • Self-documenting: Clear parameter names and descriptions

When to Use Wrappers

Use Wrappers for:

  • Creating and managing content (posts, comments)
  • Standard operations with predictable inputs
  • Reducing code complexity
  • Frequently used patterns

Use Jobs or Custom Requests when:

  • More control is needed
  • Custom parameter combinations
  • Operations not covered by wrappers
  • Uncommon workflows

Quick Example

# Using a wrapper (RECOMMENDED)
from trustcafeapiwrapper.wrappers.post.create_post import create_post

API.wrapped(create_post(
    "This is my post content",
    parent_path="/music"
))

# Using a job (for custom control)
API.run_job('post.create', {
    "postText": "Different content",
    "parent": {
        "pk": "parents-key",
        "sk": "parents-key"
    }
})

Post Wrappers

create_post()

Creates a new post with simplified parameters.

from trustcafeapiwrapper.wrappers.post.create_post import create_post

API.wrapped(create_post(
    post_text="Post content here",
    parent_path="/branch-name",
    blur_label=None,
    card_url=None,
    collaborative=False
))

Parameters:

Parameter Type Default Description
post_text str Required The text content of the post
parent_path str "/" Branch path where the post will be created
blur_label str None Optional label for blurring content
card_url str None Optional URL for card preview
collaborative bool False Enable collaborative editing

Returns: dict - Job execution result, contains success information

Example - Basic Post:

from trustcafeapiwrapper.wrappers.post.create_post import create_post

API.handle_token()

API.wrapped(create_post(
    "Welcome to TrustCafé!",
    parent_path="/"
))

Example - Post in a Specific Branch:

API.wrapped(create_post(
    "Music discussion thread",
    parent_path="/music",
    blur_label=None,
    card_url=None,
    collaborative=False
))

Example - Blurred Post:

API.wrapped(create_post(
    "Sensitive information",
    parent_path="/",
    blur_label="secret",  # Will blur until labeled
    card_url=None,
    collaborative=False
))

Example - Collaborative Post:

API.wrapped(create_post(
    "Research paper draft - collaborative editing",
    parent_path="/research",
    blur_label=None,
    card_url=None,
    collaborative=True  # Enables real-time collaboration
))

Example of performing multi-step integration with create_post and a linked resource:

# Create post
created = API.wrapped(create_post("Paper title / author", parent_path="/research"))

# If response includes pk/sk, attach a linked item (structure depends on TrustCafé's link feature)
API.run_job('some.link.create', {
    "fromPK": "paper",
    "fromSK": created.get('pk'),
    "toPK": "external-source",
    "toSK": created.get('sk')
})

update_post()

Updates an existing post.

from trustcafeapiwrapper.wrappers.post.update_post import update_post

API.wrapped(update_post(
    post_text="New post content",
    parent_path="/branch-name"
))

Parameters:

Parameter Type Default Description
post_text str Required The new text for the post
post_path str None The path of the post to update
parent_path str "/" The parent path for the post
post_key dict None A dictionary containing pk and sk of the post
blur_label str None Optional blur label for the post
card_url str None Optional card URL for the post
collaborative bool False Whether the post is collaborative

Returns: dict - Updated post data

Note: You must provide either:

  • Both post_path and parent_path, or
  • The post_key dict with pk and sk

Example - Update Text:

from trustcafeapiwrapper.wrappers.post.update_post import update_post

API.handle_token()

API.wrapped(update_post(
    post_text="Updated content here",
    parent_path="/music"
))

Example - Update with Optional Fields:

API.wrapped(update_post(
    post_text="Updated with new card",
    parent_path="/music",
    card_url="https://example.com/resource"
))

Example - Update Using post_key:

API.wrapped(update_post(
    post_text="Updated via key",
    post_key={
        "pk": "post-id",
        "sk": "post-id"
    }
))

Example - Update Blur Label:

API.wrapped(update_post(
    post_text="Sensitive content",
    parent_path="/",
    blur_label="sensitive"
))

See update_post.py for full mapping of updated fields to the server payload.

Comment Wrappers

create_comment()

Creates a new comment on a post.

from trustcafeapiwrapper.wrappers.comment.create_comment import create_comment

API.wrapped(create_comment(
    comment_text="This is a comment"
))

Parameters:

Parameter Type Default Description
comment_text str Required The comment content
post_slug str None The slug of the post the comment belongs to
parent_path str None Parent path (userprofile/slug or subwiki/slug)
post_key dict None Dictionary containing pk and sk of the post
blur_label str None Optional label for blurring comment content
version int 3 Version of comment structure to use

Returns: dict - Job execution result, contains success information

Note: You must provide either:

  • The post_key dict with pk and sk, or
  • Both post_slug and parent_path

Example - Basic Comment:

from trustcafeapiwrapper.wrappers.comment.create_comment import create_comment

API.handle_token()

API.wrapped(create_comment(
    "Great post! I really enjoyed reading it."
))

Example - Comment on a Post by Slug:

from trustcafeapiwrapper.wrappers.comment.create_comment import create_comment

API.handle_token()

API.wrapped(create_comment(
    "I agree with your point about this.",
    post_slug="target-post-slug",
    parent_path="/branch-name"
))

Example - Comment on a Post by post_key:

API.wrapped(create_comment(
    "Let's work on this together!",
    post_key={
        "pk": "post-id",
        "sk": "post-id"
    }
))

Example - Collaborative Comment:

from trustcafeapiwrapper.wrappers.comment.create_comment import create_comment

API.wrapped(create_comment(
    "Let's work on this together!",
    post_slug="current-post-slug",
    parent_path="/research"
))

Interaction Wrappers

follow()

Follow or unfollow a user or branch.

from trustcafeapiwrapper.wrappers.follow.follow import follow

API.wrapped(follow(
    entity="userprofile",
    is_following=True,
    parent_slug="philosopher-jon"
))

Parameters:

Parameter Type Default Description
entity str Required Type of entity to follow: "userprofile" or "subwiki"
is_following bool Required True to follow, False to unfollow
parent_slug str Required Slug of the entity to follow/unfollow

Returns: dict - Job execution result

Example - Follow a user:

from trustcafeapiwrapper.wrappers.follow.follow import follow

API.wrapped(follow(
    entity="userprofile",
    is_following=True,
    parent_slug="philosopher-jon"
))

Example - Unfollow a branch:

API.wrapped(follow(
    entity="subwiki",
    is_following=False,
    parent_slug="music"
))

react()

React to a post or comment (like, heart, etc.). This single endpoint handles creating, updating, and deleting reactions — the logic is handled server-side.

from trustcafeapiwrapper.wrappers.reaction.react import react

API.wrapped(react(
    reaction_type="like",
    parent_path="/music",
    item_path="/music/my-post-slug"
))

Parameters:

Parameter Type Default Description
reaction_type str Required Reaction type (e.g., "like", "heart", "fire")
parent_path str None Parent path (e.g., "/music")
item_path str None Item path (e.g., "/music/my-post-slug")
item_key dict None Dict with pk and sk keys

Returns: dict - Job execution result

Note: You must provide either:

  • Both parent_path and item_path, or
  • The item_key dict with pk and sk

Example - React by paths:

from trustcafeapiwrapper.wrappers.reaction.react import react

API.wrapped(react(
    reaction_type="like",
    parent_path="/music",
    item_path="/music/my-post-slug"
))

Example - React by key:

API.wrapped(react(
    reaction_type="heart",
    item_key={
        "pk": "post#my-post-slug",
        "sk": "post#my-post-slug"
    }
))

trust()

Set trust level for a user profile.

from trustcafeapiwrapper.wrappers.trust.trust import trust

API.wrapped(trust(
    trustLevel="trusted",
    userprofile_path="/userprofile/philosopher-jon"
))

Parameters:

Parameter Type Default Description
trustLevel str Required Trust level: "trusted", "neutral", or "distrusted"
userprofile_path str Required Path to the user profile (e.g., "/userprofile/slug")

Returns: dict - Job execution result

Example:

from trustcafeapiwrapper.wrappers.trust.trust import trust

API.wrapped(trust(
    trustLevel="trusted",
    userprofile_path="/userprofile/philosopher-jon"
))

votecast()

Cast a vote on a post or comment.

from trustcafeapiwrapper.wrappers.vote.votecast import votecast

API.wrapped(votecast(
    vote="up",
    parent_path="/music",
    item_path="/music/my-post-slug"
))

Parameters:

Parameter Type Default Description
vote str Required Vote value (e.g., "up", "down")
parent_path str None Parent path
item_path str None Item path
item_key dict None Dict with pk and sk keys

Returns: dict - Job execution result

Note: You must provide either:

  • Both parent_path and item_path, or
  • The item_key dict with pk and sk

Example - Vote by paths:

from trustcafeapiwrapper.wrappers.vote.votecast import votecast

API.wrapped(votecast(
    vote="up",
    parent_path="/music",
    item_path="/music/my-post-slug"
))

Example - Vote by key:

API.wrapped(votecast(
    vote="down",
    item_key={
        "pk": "post#my-post-slug",
        "sk": "post#my-post-slug"
    }
))

Wrappers Best Practices

1. Provide Context in Parent Paths

Good - Explicit paths:

API.wrapped(create_post(
    "Content",
    parent_path="/music/discussion"  # Clear and specific
))

Bad - Empty paths:

API.wrapped(create_post(
    "Content",
    parent_path="/"  # Default root - less clear intention
))

2. Handle Phone Numbers in Content

When phone numbers appear in text, leave them as-is. The API wraps the input string, so 555-1234 stays 555-1234. No HTML is added.

3. Path Normalization

Paths are used directly without extra normalization:

# Use with leading slash
API.wrapped(create_post(
    "Content",
    parent_path="/music"
))

# Or without (both should work)
API.wrapped(create_post(
    "Content",
    parent_path="music"
))

4. Validate Parent Exists

It's good practice to verify the parent path exists:

# Check if branch exists
branches = API.run_job('branch.listbyname')

if branches.get('Items'):
    branch_slugs = [b.get('slug') for b in branches.get('Items', [])]
    if 'music' in branch_slugs:
        # Branch exists, proceed with post
        API.wrapped(create_post(
            "Content",
            parent_path="/music"
        ))
    else:
        print("Branch 'music' does not exist")
else:
    print("No branches found")

5. Handle Responses

from trustcafeapiwrapper.wrappers.post.create_post import create_post

response = API.wrapped(create_post(
    "My post",
    parent_path="/music"
))

# Check for success
if response and 'success' in response:
    print("Post created successfully!")
    print(f"Post ID: {response.get('pk')}")
else:
    print("Failed to create post")
    print(f"Error: {response.get('error')}")

6. Error Handling

from trustcafeapiwrapper.wrappers.post.create_post import create_post
import logging

logger = logging.getLogger(__name__)

try:
    API.handle_token()  # Ensure authenticated
    API.wrapped(create_post(
        "Post content",
        parent_path="/music"
    ))
    logger.info("Post created successfully")
except Exception as e:
    logger.error(f"Failed to create post: {e}")
    # Handle error - maybe retry, notify admin, etc.

Wrapper vs Job

Feature Wrappers Jobs
Simplicity
Flexibility
Default Values Yes No
Parameter Validation Yes No
Common Operations Many None
Custom Operations No Yes
Learning Curve Low High

Replacement Examples

Example 1: Create Post

# Wrapper - Simple
API.wrapped(create_post(
    "Content",
    parent_path="/music"
))

# Job - More complex
API.run_job('post.create', {
    "postText": "Content",
    "parent": {
        "pk": "encode(parent_path)",
        "sk": "encode(parent_path)"
    }
})

Example 2: Update Post

# Wrapper
API.wrapped(update_post(
    post_text="New content",
    parent_path="/music"
))

# Job
API.run_job('post.update', {
    "pk": "post-id",
    "sk": "post-id",
    "newPostText": "New content"
})

Example 3: Create Comment

# Wrapper
API.wrapped(create_comment(
    "My comment",
    post_slug="post-id",
    parent_path="/branch"
))

# Job
API.run_job('comment.create', {
    "commentText": "My comment",
    "parent": {
        "pk": "post-id",
        "sk": "post-id"
    }
})

When to Use Each

Use Wrappers When:

  • Common operation (create/update post/comment)
  • Multiple optional parameters
  • Want concise, readable code
  • Acceptable default behavior

Use Jobs When:

  • Rarely used operation
  • Very specific parameter combinations
  • Custom job names unsupported by wrappers
  • Need maximum flexibility

Creating Custom Wrappers

You can create your own wrappers for repeated operations:

# Custom post wrapper
def create_in_branch(API, branch: str, content: str, create_card: bool = False):
    """
    Helper wrapper for creating posts in specific branches.

    Args:
        API: The APIClient instance
        branch: Branch name (e.g., "music", "science")
        content: Post content
        create_card: Whether to create a card URL

    Returns:
        dict: API response
    """
    card_url = "https://example.com/card" if create_card else None

    from trustcafeapiwrapper.wrappers.post.create_post import create_post

    return API.wrapped(create_post(
        content,
        parent_path=f"/{branch}",
        card_url=card_url
    ))

# Usage
API.handle_token()
result = create_in_branch(API, "music", "New music discussion")

# Or with card
result = create_in_branch(API, "science", "Research paper abstract", create_card=True)

Summary

Wrappers provide a convenient, safe way to perform common operations with the TrustCafé API. For most use cases, wrappers reduce boilerplate and prevent configuration errors. However, jobs offer greater flexibility when standard wrappers don't meet your needs.

Choose wisely:

  • Wrappers for standard operations and simplicity
  • Jobs for custom operations and maximum control