PerspectPerspectDocs
Go to Admin
View as Markdown

Data Loading

The PerspectAPI v2 SDK provides direct methods for loading content, products, and categories with cursor-based pagination and auto-pagination support.

Quick Start

import { PerspectApiV2Client } from 'perspectapi-ts-sdk';

const client = new PerspectApiV2Client({
  baseUrl: process.env.PERSPECTAPI_BASE_URL!,
  apiKey: process.env.PERSPECTAPI_API_KEY!
});

// Load published posts
const posts = await client.content.list('my-site', {
  type: 'post',
  status: 'publish',
  limit: 10
});

// Load products
const products = await client.products.list('my-site', {
  published: true,
  limit: 20
});

Content

List Content

const posts = await client.content.list('my-site', {
  type: 'post',        // "post" | "page" | "block"
  status: 'publish',   // "draft" | "publish" | "private" | "trash" | "scheduled"
  limit: 10,
  slug_prefix: 'blog',
  search: 'tutorial'
});

// Response:
// {
//   object: "list",
//   data: [{ object: "content", id: "cnt_42", title: "...", ... }],
//   has_more: true,
//   url: "/v2/sites/my-site/content"
// }

Get by ID or Slug

// By prefixed ID
const post = await client.content.get('my-site', 'cnt_42');

// By slug
const post = await client.content.get('my-site', 'getting-started');

Auto-Paginate All Content

for await (const post of client.content.listAutoPaginated('my-site', {
  type: 'post',
  status: 'publish'
})) {
  console.log(post.title);
}

Products

List Products

const products = await client.products.list('my-site', {
  published: true,
  category_id: 'cat_5',
  slug_prefix: 'widgets',
  limit: 20
});

Get by ID or Slug

const product = await client.products.get('my-site', 'prod_123');
const product = await client.products.get('my-site', 'premium-widget');

Auto-Paginate

for await (const product of client.products.listAutoPaginated('my-site', {
  published: true
})) {
  console.log(`${product.name}: $${product.price}`);
}

Categories

const categories = await client.categories.list('my-site', {
  type: 'product'  // "post" | "product"
});

Server Framework Examples

Remix Loader

import { PerspectApiV2Client } from 'perspectapi-ts-sdk';

export async function loader() {
  const client = new PerspectApiV2Client({
    baseUrl: process.env.API_URL!,
    apiKey: process.env.API_KEY!
  });

  const [posts, products] = await Promise.all([
    client.content.list('my-site', { type: 'post', status: 'publish', limit: 10 }),
    client.products.list('my-site', { published: true, limit: 12 }),
  ]);

  return { posts: posts.data, products: products.data };
}

Next.js App Route

import { PerspectApiV2Client } from 'perspectapi-ts-sdk';

const client = new PerspectApiV2Client({
  baseUrl: process.env.API_URL!,
  apiKey: process.env.API_KEY!
});

export default async function BlogPage() {
  const posts = await client.content.list('my-site', {
    type: 'post',
    status: 'publish',
    limit: 20
  });

  return (
    <div>
      {posts.data.map(post => (
        <article key={post.id}>
          <h2>{post.title}</h2>
          <p>{post.slug}</p>
        </article>
      ))}
      {posts.has_more && <LoadMoreButton />}
    </div>
  );
}

Cloudflare Worker

import { PerspectApiV2Client } from 'perspectapi-ts-sdk';

export default {
  async fetch(request: Request, env: Env) {
    const client = new PerspectApiV2Client({
      baseUrl: env.API_URL,
      apiKey: env.API_KEY
    });

    const url = new URL(request.url);
    const slug = url.pathname.slice(1); // e.g., "/my-post" -> "my-post"

    const post = await client.content.get('my-site', slug);

    return new Response(JSON.stringify(post), {
      headers: { 'Content-Type': 'application/json' }
    });
  }
};

Cursor Pagination

All list methods use cursor-based pagination via starting_after and ending_before:

// First page
const page1 = await client.content.list('my-site', { limit: 10 });

// Next page (using the last item's ID as cursor)
if (page1.has_more) {
  const lastId = page1.data[page1.data.length - 1].id;
  const page2 = await client.content.list('my-site', {
    limit: 10,
    starting_after: lastId
  });
}

Or use listAutoPaginated() to iterate all items automatically:

const allPosts: V2Content[] = [];
for await (const post of client.content.listAutoPaginated('my-site', { type: 'post' })) {
  allPosts.push(post);
}