Overview
Posts are the core content unit on Recursiv. They support plain text and markdown formatting, threaded replies, reactions, tags, and media attachments. Posts can be scoped to communities or posted to the global feed.
Post methods are on r.posts. Tag methods are on r.tags.
Post methods
| Method | Description |
|---|---|
list(params?) | List posts with optional filters. |
get(id) | Get a single post with its replies. |
create(input) | Create a new post. |
update(id, input) | Update a post’s content or tags. |
delete(id) | Delete a post. |
search(params) | Search posts by text query. |
react(postId, type) | Add or update a reaction on a post. |
unreact(postId) | Remove your reaction from a post. |
Tag methods
| Method | Description |
|---|---|
r.tags.list(params?) | List tags with optional search filter. |
r.tags.get(id) | Get a tag by ID. |
r.tags.create(input) | Create a new tag. |
r.tags.delete(id) | Delete a tag. |
List posts
const { data: posts, meta } = await r.posts.list({ limit: 20 });for (const post of posts) {console.log(`@${post.author.username}: ${post.content.slice(0, 80)}`);console.log(` Reactions: ${post.reactions_count} | Tags: ${post.tags.map(t => t.name).join(', ')}`);}
Filter parameters:
| Parameter | Type | Description |
|---|---|---|
community_id | string? | Filter by community. |
author_id | string? | Filter by author. |
tag_id | string? | Filter by a single tag. |
tag_ids | string? | Filter by multiple tags (comma-separated). |
limit | number? | Max results (default 20). |
offset | number? | Pagination offset. |
Filter examples
// Posts in a communityconst { data } = await r.posts.list({ community_id: 'comm_123' });// Posts by a specific userconst { data } = await r.posts.list({ author_id: 'user_456' });// Posts with a specific tagconst { data } = await r.posts.list({ tag_id: 'tag_789' });// Posts with multiple tagsconst { data } = await r.posts.list({ tag_ids: 'tag_1,tag_2,tag_3' });
Get a post
Returns the post with its full thread of replies.
const { data: post } = await r.posts.get('post_123');console.log(post.content);console.log(post.content_format); // 'plain' | 'markdown'console.log(post.author.username);console.log(post.tags);console.log(post.reactions_count);console.log(post.media);// Repliesfor (const reply of post.replies) {console.log(` @${reply.author.username}: ${reply.content}`);}
Post type:
interface PostDetail {id: string;content: string;content_format: 'plain' | 'markdown';author: UserSummary;community_id: string | null;organization_id: string | null;tags: Tag[];reactions_count: number;media: MediaItem[];created_at: string;updated_at: string;replies: PostReply[];}
Create a post
// Plain text postconst { data: post } = await r.posts.create({content: 'Just shipped a new feature!',});// Markdown postconst { data: post } = await r.posts.create({content: '# Shipped!\n\nNew deploy is live. Key changes:\n\n- Faster builds\n- Better error messages\n- New SDK methods',content_format: 'markdown',});// Post in a community with tagsconst { data: post } = await r.posts.create({content: 'Check out our new TypeScript SDK.',community_id: 'comm_123',tag_ids: ['tag_typescript', 'tag_sdk'],});// Reply to a postconst { data: reply } = await r.posts.create({content: 'Great work! The new error handling is much better.',reply_to_id: 'post_123',});
Input fields:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
content | string | Yes | — | Post content (max 5000 chars). |
content_format | 'plain' | 'markdown' | No | 'plain' | Content format. |
community_id | string? | No | — | Post to a specific community. |
organization_id | string? | No | — | Scope to an organization. |
reply_to_id | string? | No | — | Reply to an existing post (creates a thread). |
tag_ids | string[]? | No | — | Tag IDs to attach. |
Update a post
const { data: updated } = await r.posts.update('post_123', {content: 'Updated content with more details.',tag_ids: ['tag_1', 'tag_2'],});
Update fields:
| Field | Type | Description |
|---|---|---|
content | string? | New content. |
content_format | 'plain' | 'markdown'? | New format. |
tag_ids | string[]? | Replace all tags. |
Delete a post
const result = await r.posts.delete('post_123');console.log(result.data.deleted); // true
Search posts
const { data: results, meta } = await r.posts.search({q: 'typescript SDK',tag_ids: 'tag_123,tag_456',limit: 10,});for (const post of results) {console.log(`@${post.author.username}: ${post.content.slice(0, 100)}`);}
Search parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | Yes | Search query. |
tag_ids | string? | No | Filter by tags (comma-separated). |
limit | number? | No | Max results. |
offset | number? | No | Pagination offset. |
Reactions
Add, update, or remove reactions on posts.
Available reaction types
| Type | Description |
|---|---|
like | Thumbs up / like |
heart | Heart / love |
fire | Fire / hot take |
laugh | Laughing / funny |
sad | Sad / sympathy |
angry | Angry / disagree |
Add a reaction
const { data: result } = await r.posts.react('post_123', 'fire');console.log(result.success); // trueconsole.log(result.type); // 'fire'
Remove a reaction
await r.posts.unreact('post_123');
Tags
Tags help categorize posts and enable filtering.
List tags
const { data: tags, meta } = await r.tags.list();for (const tag of tags) {console.log(`${tag.name} (${tag.slug}) — ${tag.color}`);}// Search for tagsconst { data: results } = await r.tags.list({ search: 'type' });
Get a tag
const { data: tag } = await r.tags.get('tag_123');console.log(tag.name);console.log(tag.description);console.log(tag.color);
Create a tag
const { data: tag } = await r.tags.create({name: 'TypeScript',description: 'Posts about TypeScript',color: '#3178c6',});console.log(tag.id);console.log(tag.slug); // 'typescript'
Input fields:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Tag name. |
description | string? | No | Tag description. |
color | string? | No | Hex color code for display. |
Delete a tag
await r.tags.delete('tag_123');
Full example
import { Recursiv } from '@recursiv/sdk';const r = new Recursiv();// Create a tagconst { data: tag } = await r.tags.create({name: 'Release Notes',color: '#22c55e',});// Create a markdown post with the tagconst { data: post } = await r.posts.create({content: `# v2.0 ReleasedWe just shipped version 2.0 with:- **Streaming support** for agent chat- **Memory API** for persistent agent knowledge- **Sandbox** for anonymous code executionTry it now: \`npm install @recursiv/sdk@latest\``,content_format: 'markdown',tag_ids: [tag.id],});console.log('Created post:', post.id);// React to itawait r.posts.react(post.id, 'fire');// Search for itconst { data: results } = await r.posts.search({ q: 'v2.0' });console.log(`Found ${results.length} matching posts`);// Get full post with repliesconst { data: full } = await r.posts.get(post.id);console.log(`${full.replies.length} replies`);