---
title: "Ask for a client PDF of a site's Search figures"
method: POST
path: "/v1/sites/{site}/search/pdfs"
tags: ["gsc"]
---

# Ask for a client PDF of a site's Search figures

`POST /v1/sites/{site}/search/pdfs`

## Request

- Base URL: `https://frontshelf.io/api`
- URL: `https://frontshelf.io/api/v1/sites/{site}/search/pdfs`
- Auth: HTTP bearer

Ask for a client PDF of one site's Search figures: a finished month (`month`) or a range of finished Pacific days (`start`, `end`), with the sections chosen, branded with the workspace's name and logo. Every figure reads final days only. The answer is the PDF with its `state`: queued or building, waiting (a prerequisite that can return, with its `sentence` and `next_try_at`), ready, failed or invalidated. An identical request answers the existing PDF rather than making a second. Nothing is sent to anyone. Paid (reports, and ga4, audit_joins, index or alerts for those sections): BILLING_REQUIRED on a site without them. Next: call gsc_pdfs_get until it is ready; a ready PDF carries its download link.

## Path parameters

- `site` string, required: Site ID (site_…), origin (https://example.com), or bare domain, resolved server-side; the response carries the canonical ID.

## Request body

- object
  - `month` string: A finished calendar month, YYYY-MM (Pacific days). Give `month`, or `start` and `end`, never both.
  - `start` string: With `end`: the first day of a range of finished Pacific days, YYYY-MM-DD.
  - `end` string: With `start`: the last day of the range.
  - `sections` string[]: The sections, each one or two pages: summary (always: clicks, impressions, CTR and position against the period before and a year earlier, the chart), movers (the queries and pages whose clicks rose and fell most), groups (page groups and keyword clusters), notes (notes and Google updates with their verdicts), indexing, audit (the newest crawl's scores and its ten issues with the most clicks), analytics (Google Analytics organic and both AI figures), alerts (the falls alerted in the period). Default: summary, movers, groups, notes, audit.
  - `dry_run` boolean: true: check the call and say what it would do, without doing it.
  - `confirm` boolean: true: go ahead with a change that asks for confirmation.

## Response `200`

Ask for a client PDF of a site's Search figures

- object
  - `summary` string, required: The answer in one or two sentences, with the numbers it rests on.
  - `warnings` string[], required: What limits this answer (a cap, a read that was cut short). Empty when nothing does.
  - `next_actions` object[], required: What to call next, best first. Follow them.
    - `capability` string, required: What to call next: a capability.
    - `arguments` object, required: Its arguments, complete; pass them as they are.
    - `instruction` string, required: What to do, written to you.
  - `id` string, required: The PDF's id (spdf_…): what gsc_pdfs_get takes.
  - `site_id` string, required: The site's canonical id.
  - `period` object, required: The Pacific days it covers.
    - `start` string, required
    - `end` string, required
  - `sections` string[], required
  - `state` 'queued' | 'building' | 'waiting' | 'ready' | 'failed' | 'invalidated', required: queued or building (the renderer makes it), waiting (a prerequisite that can return), ready, failed, or invalidated (withdrawn: data it held was erased).
  - `reason` 'no_blob_store' | 'not_final' | 'not_connected' | 'gated' | 'render_failed' | 'store_failed' | 'expired' | 'source_erased' | 'analytics_erased': Why it waits, failed or was withdrawn.
  - `next_try_at` string: A waiting PDF: when Frontshelf tries again.
  - `ready_at` string: An instant, ISO 8601.
  - `bytes` integer: A ready PDF's size.
  - `at` string: A withdrawn PDF: when it was withdrawn.
  - `sentence` string, nullable, required: The state in words: what a waiting PDF waits for and when it tries again, why one failed, when and why one was withdrawn; null for queued, building and ready.
  - `download_url` string, nullable, required: A ready PDF's signed download link, good for 15 minutes with no Authorization header; null in every other state. A secret: hand it to your human, never anywhere else.

## Other responses

- `400`: SEARCH_SPEC_INVALID, VALIDATION_FAILED
- `401`: UNAUTHENTICATED
- `402`: BILLING_REQUIRED
- `403`: SCOPE_DENIED
- `404`: SITE_NOT_FOUND
- `409`: AMBIGUOUS_SITE, SEARCH_NOT_CONNECTED, AGENT_STOPPED
- `503`: DEPENDENCY_UNAVAILABLE

---

[API](https://skmtc.dev/frontshelf/apis/frontshelf-api.md) · [All operations](https://skmtc.dev/frontshelf/apis/frontshelf-api/llms.txt) · [OpenAPI document](https://skmtc.dev/frontshelf/apis/frontshelf-api/revisions/ce3602d26c7c?raw)
