Brand Studio docs
Engineering manualAPI route source

/api/brands/site-pages

Exact current route handler: hosted-app/app/api/brands/site-pages/route.js

Methods: GET, POST. Input signals: query parameters. Literal response-status signals: none detected.

Source: hosted-app/app/api/brands/site-pages/route.js. Imports: ../../../../lib/bounded-http.mjs, ../../../../lib/comprehensive-pull.mjs, ../../../../lib/site-pages.mjs, ../../../../lib/supabase-rest.mjs, next/server. Exact source is shown for inspection; its presence does not prove authentication, validation or live behavior.

All API routes · API and execution contract

// /api/brands/site-pages — the pages a saved brand lists in its own sitemaps.
//
//   GET ?domain=[&pages=1&offset=&limit=]  the latest read, what changed since
//                                          the previous one, and optionally a
//                                          slice of the page list (read_reports)
//   POST { domain }                        read the sitemaps now (free; at most
//                                          once every ten minutes per brand)
//
// Reading needs a browser session or an API key with run_pulls; assistant
// connections are read-only. See lib/site-pages.mjs.

import { NextResponse } from "next/server";
import { supabaseConfigFromEnv } from "../../../../lib/supabase-rest.mjs";
import { bearerTokenFromHeader } from "../../../../lib/comprehensive-pull.mjs";
import { readBoundedJsonRequest } from "../../../../lib/bounded-http.mjs";
import { getSitePages, takeSitePages } from "../../../../lib/site-pages.mjs";

export const runtime = "nodejs";
export const dynamic = "force-dynamic";
export const maxDuration = 60;

const PRIVATE = { "cache-control": "private, no-store", "x-content-type-options": "nosniff" };
const reply = (result) => NextResponse.json(result.body, { status: result.http_status, headers: PRIVATE });
const tokenOf = (request) => bearerTokenFromHeader(request.headers.get("authorization"));

export async function GET(request) {
  const params = new URL(request.url).searchParams;
  return reply(await getSitePages({ token: tokenOf(request), config: supabaseConfigFromEnv(process.env), domain: params.get("domain") || "",
    readId: params.get("read_id") || "", pages: params.get("pages") === "1", offset: params.has("offset") ? Number(params.get("offset")) : 0, limit: params.has("limit") ? Number(params.get("limit")) : 200 }));
}

export async function POST(request) {
  let body;
  try { body = await readBoundedJsonRequest(request, 4096); }
  catch (error) { return NextResponse.json({ status: "refused", reason: error.message }, { status: error.httpStatus || 400, headers: PRIVATE }); }
  return reply(await takeSitePages({ token: tokenOf(request), config: supabaseConfigFromEnv(process.env), body: body || {} }));
}