Brand Studio docs
Engineering manualAPI route source

/api/brands/changes

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

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

Source: hosted-app/app/api/brands/changes/route.js. Imports: ../../../../lib/basic-watches.mjs, ../../../../lib/comprehensive-pull.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

// GET /api/brands/changes?days=7 — what changed across the account's brands:
// saved reads with changes (by hand or by a weekly check) and weekly check
// results, grouped by brand. Sessions and API keys with read_reports. Reads
// stored data only. See lib/basic-watches.mjs.

import { NextResponse } from "next/server";
import { supabaseConfigFromEnv } from "../../../../lib/supabase-rest.mjs";
import { bearerTokenFromHeader } from "../../../../lib/comprehensive-pull.mjs";
import { listRecentBrandChanges, DIGEST_LIMITS } from "../../../../lib/basic-watches.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" };

export async function GET(request) {
  const params = new URL(request.url).searchParams;
  const raw = params.get("days");
  const days = raw === null || raw === "" ? DIGEST_LIMITS.defaultDays : Number(raw);
  const result = await listRecentBrandChanges({ token: bearerTokenFromHeader(request.headers.get("authorization")), config: supabaseConfigFromEnv(process.env), days, domain: params.get("domain") || "", snapshotAt: params.get("until") || null, offset: Number(params.get("offset") || 0), limit: Number(params.get("limit") || DIGEST_LIMITS.maxRows) });
  return NextResponse.json(result.body, { status: result.http_status, headers: PRIVATE });
}