Upstreet Docs
    SDK

    Manage blog projects and posts—create projects, list posts, and publish AI-generated content.

    Blog Subclient

    The client.blog subclient lets you manage blog projects and posts—AI-generated articles with titles, prompts, and hero images. Create projects, list and create posts, and publish content that NPCs and the platform can use.


    Projects API

    MethodSignatureDescription
    blog.projects.list() => Promise<BlogProject[]>List all blog projects
    blog.projects.getById(id) => Promise<BlogProject | null>Get project by ID
    blog.projects.create(params) => Promise<BlogProject>Create a new project
    blog.projects.update(params) => Promise<BlogProject>Update project settings
    blog.projects.delete(params) => Promise<void>Delete a project

    Posts API

    MethodSignatureDescription
    blog.posts.list(projectId) => Promise<BlogPostSummary[]>List posts in a project
    blog.posts.get(projectId, opts) => Promise<BlogPost | null>Get post by ID or slug
    blog.posts.create(projectId, params) => Promise<BlogPost>Create a new post (triggers AI generation)
    blog.posts.delete(projectId, id) => Promise<void>Delete a post

    Projects

    blog.projects.list()

    blog.projects.list(): Promise<BlogProject[]>

    Returns all blog projects for the authenticated user.

    const projects = await client.blog.projects.list();

    blog.projects.getById(id)

    blog.projects.getById(id: string): Promise<BlogProject | null>

    Fetches a project by ID. Returns null if not found.

    const project = await client.blog.projects.getById('project-uuid');

    blog.projects.create(params)

    blog.projects.create(params: {
      name: string;
      description?: string;
      visibility?: 'public' | 'private';
    }): Promise<BlogProject>

    Creates a new blog project.

    const project = await client.blog.projects.create({
      name: 'Dev Blog',
      description: 'Updates and tutorials',
      visibility: 'public',
    });

    blog.projects.update(params)

    blog.projects.update(params: Partial<BlogProject> & { id: string }): Promise<BlogProject>

    Updates project settings. Include id in params.

    await client.blog.projects.update({
      id: project.id,
      description: 'Updated description',
    });

    blog.projects.delete(params)

    blog.projects.delete(params: { id: string }): Promise<void>

    Deletes a blog project.

    await client.blog.projects.delete({ id: project.id });

    Posts

    blog.posts.list(projectId)

    blog.posts.list(projectId: string): Promise<BlogPostSummary[]>

    Lists all posts in a project.

    const posts = await client.blog.posts.list(project.id);

    blog.posts.get(projectId, opts)

    blog.posts.get(projectId: string, opts: { id?: string; slug?: string }): Promise<BlogPost | null>

    Gets a post by ID or slug. Provide either id or slug.

    const byId = await client.blog.posts.get(project.id, { id: 'post-uuid' });
    const bySlug = await client.blog.posts.get(project.id, { slug: 'my-first-post' });

    blog.posts.create(projectId, params)

    blog.posts.create(projectId: string, params: {
      title?: string;
      prompt?: string;
      images?: string[];
    }): Promise<BlogPost>

    Creates a new blog post. Triggers AI generation—the post starts in pending/generating and progresses to completed.

    Creating a post kicks off asynchronous AI generation. Poll the post (e.g. via blog.posts.get) or use the platform UI to track status and progress.

    const post = await client.blog.posts.create(project.id, {
      title: 'Getting Started',
      prompt: 'A beginner-friendly intro to the platform',
    });

    blog.posts.delete(projectId, id)

    blog.posts.delete(projectId: string, id: string): Promise<void>

    Deletes a blog post.

    await client.blog.posts.delete(project.id, post.id);

    BlogPost Fields

    FieldTypeDescription
    idstringPost ID
    slugstringURL-friendly slug
    titlestringPost title
    published_atstringPublication timestamp
    markdownstring | nullGenerated markdown content
    status'pending' | 'generating' | 'completed' | 'failed'Generation status
    progressnumberGeneration progress (0–1)
    streaming_markdownstring | nullPartial content while generating

    Code Examples

    import { PUClient } from 'pu-client';
    
    const client = new PUClient({ apiKey: process.env.PU_API_KEY! });
    
    const project = await client.blog.projects.create({
      name: 'AI News',
      visibility: 'public',
    });
    
    const post = await client.blog.posts.create(project.id, {
      title: 'Welcome to the Future',
      prompt: 'An optimistic take on AI in 2025',
    });
    
    console.log(`Post created: ${post.slug} (status: ${post.status})`);
    import { PUClient } from 'pu-client';
    
    const client = new PUClient({ apiKey: process.env.PU_API_KEY! });
    
    const project = await client.blog.projects.getById('project-uuid');
    if (!project) return;
    
    const posts = await client.blog.posts.list(project.id);
    const post = await client.blog.posts.get(project.id, { slug: 'welcome' });
    
    if (post?.status === 'completed') {
      console.log(post.markdown);
    }

    Next Steps