Posts & Feeds
Posts & Feeds
Content feeds with markdown, reactions, threads, and tags
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
1 const { data: posts, meta } = await r.posts.list({ limit: 20 }); 2 3 for (const post of posts) { 4 console.log(`@${post.author.username}: ${post.content.slice(0, 80)}`); 5 console.log(` Reactions: ${post.reactions_count} | Tags: ${post.tags.map(t => t.name).join(', ')}`); 6 }
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
1 // Posts in a community 2 const { data } = await r.posts.list({ community_id: 'comm_123' }); 3 4 // Posts by a specific user 5 const { data } = await r.posts.list({ author_id: 'user_456' }); 6 7 // Posts with a specific tag 8 const { data } = await r.posts.list({ tag_id: 'tag_789' }); 9 10 // Posts with multiple tags 11 const { 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.
1 const { data: post } = await r.posts.get('post_123'); 2 3 console.log(post.content); 4 console.log(post.content_format); // 'plain' | 'markdown' 5 console.log(post.author.username); 6 console.log(post.tags); 7 console.log(post.reactions_count); 8 console.log(post.media); 9 10 // Replies 11 for (const reply of post.replies) { 12 console.log(` @${reply.author.username}: ${reply.content}`); 13 }
Post type:
1 interface PostDetail { 2 id: string; 3 content: string; 4 content_format: 'plain' | 'markdown'; 5 author: UserSummary; 6 community_id: string | null; 7 organization_id: string | null; 8 tags: Tag[]; 9 reactions_count: number; 10 media: MediaItem[]; 11 created_at: string; 12 updated_at: string; 13 replies: PostReply[]; 14 }
Create a post
1 // Plain text post 2 const { data: post } = await r.posts.create({ 3 content: 'Just shipped a new feature!', 4 }); 5 6 // Markdown post 7 const { data: post } = await r.posts.create({ 8 content: '# Shipped!\n\nNew deploy is live. Key changes:\n\n- Faster builds\n- Better error messages\n- New SDK methods', 9 content_format: 'markdown', 10 }); 11 12 // Post in a community with tags 13 const { data: post } = await r.posts.create({ 14 content: 'Check out our new TypeScript SDK.', 15 community_id: 'comm_123', 16 tag_ids: ['tag_typescript', 'tag_sdk'], 17 }); 18 19 // Reply to a post 20 const { data: reply } = await r.posts.create({ 21 content: 'Great work! The new error handling is much better.', 22 reply_to_id: 'post_123', 23 });
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
1 const { data: updated } = await r.posts.update('post_123', { 2 content: 'Updated content with more details.', 3 tag_ids: ['tag_1', 'tag_2'], 4 });
Update fields:
| Field | Type | Description |
|---|---|---|
content | string? | New content. |
content_format | 'plain' | 'markdown'? | New format. |
tag_ids | string[]? | Replace all tags. |
Delete a post
1 const result = await r.posts.delete('post_123'); 2 console.log(result.data.deleted); // true
Search posts
1 const { data: results, meta } = await r.posts.search({ 2 q: 'typescript SDK', 3 tag_ids: 'tag_123,tag_456', 4 limit: 10, 5 }); 6 7 for (const post of results) { 8 console.log(`@${post.author.username}: ${post.content.slice(0, 100)}`); 9 }
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
1 const { data: result } = await r.posts.react('post_123', 'fire'); 2 console.log(result.success); // true 3 console.log(result.type); // 'fire'
Remove a reaction
1 await r.posts.unreact('post_123');
Tags
Tags help categorize posts and enable filtering.
List tags
1 const { data: tags, meta } = await r.tags.list(); 2 3 for (const tag of tags) { 4 console.log(`${tag.name} (${tag.slug}) — ${tag.color}`); 5 } 6 7 // Search for tags 8 const { data: results } = await r.tags.list({ search: 'type' });
Get a tag
1 const { data: tag } = await r.tags.get('tag_123'); 2 console.log(tag.name); 3 console.log(tag.description); 4 console.log(tag.color);
Create a tag
1 const { data: tag } = await r.tags.create({ 2 name: 'TypeScript', 3 description: 'Posts about TypeScript', 4 color: '#3178c6', 5 }); 6 7 console.log(tag.id); 8 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
1 await r.tags.delete('tag_123');
Full example
1 import { Recursiv } from '@recursiv/sdk'; 2 3 const r = new Recursiv(); 4 5 // Create a tag 6 const { data: tag } = await r.tags.create({ 7 name: 'Release Notes', 8 color: '#22c55e', 9 }); 10 11 // Create a markdown post with the tag 12 const { data: post } = await r.posts.create({ 13 content: `# v2.0 Released 14 15 We just shipped version 2.0 with: 16 17 - **Streaming support** for agent chat 18 - **Memory API** for persistent agent knowledge 19 - **Sandbox** for anonymous code execution 20 21 Try it now: \`npm install @recursiv/sdk@latest\``, 22 content_format: 'markdown', 23 tag_ids: [tag.id], 24 }); 25 26 console.log('Created post:', post.id); 27 28 // React to it 29 await r.posts.react(post.id, 'fire'); 30 31 // Search for it 32 const { data: results } = await r.posts.search({ q: 'v2.0' }); 33 console.log(`Found ${results.length} matching posts`); 34 35 // Get full post with replies 36 const { data: full } = await r.posts.get(post.id); 37 console.log(`${full.replies.length} replies`);