blawgy-com Existing pages API

The inventory of pages that already exist on the site.

Operations 6

GET /sites/{site}/pages/existing List existing pages #
POST /sites/{site}/pages/existing/import Import existing pages #
POST /sites/{site}/pages/existing/include Check a skipped page anyway #
POST /sites/{site}/pages/existing/remove Remove an existing page #
POST /sites/{site}/pages/existing/restore Restore a removed existing page #
POST /sites/{site}/pages/existing/sync Re-scan existing pages #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/blawgy-com:blawgy-com-existing-pages-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

blawgy-com-existing-pages-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Blawgy Existing pages API
  version: 1.0.0
  description: 'The Blawgy API: everything the Blawgy dashboard and MCP server can do, over HTTPS. Every endpoint is also an MCP tool (`x-mcp-tool`); both transports share keys, site scoping, plan gating, rate limits and the audit log.


    **Authentication.** `Authorization: Bearer blk_live_...` with an API key from Settings > Account > AI agents in the Blawgy dashboard (or an OAuth access token issued for this host). Keys are server-side only: there is no CORS on /v1, except the keyless public content endpoints under `/public`.


    **Arguments.** GET endpoints take theirs as query parameters; POST, PATCH, PUT and DELETE take a JSON body (`Content-Type: application/json`), and their query string carries only `dryRun`. Unknown arguments are a 400, never silently dropped.


    **Errors.** Every non-2xx answer is `{ "error": { "code", "message", "details"?, "requestId" } }`. Every response carries `Request-Id`.


    **Pagination.** Lists answer `{ data, nextCursor, total? }` and take `?limit=` and `?cursor=` (the previous page''s `nextCursor`). `limit` is capped per endpoint (never above 200); a larger value is clamped to the cap.


    **Idempotency.** Send `Idempotency-Key` on POST, PATCH, PUT or DELETE to make a retry safe for 24 hours: the same key and request replays the stored answer (`Idempotent-Replayed: true`); the same key with a different request is a 422.


    **Dry runs.** `?dryRun=true` on any write runs every gate (auth, scope, plan, validation) and returns a one-line summary without doing anything.


    **Rate limits.** 240 calls a minute and 6,000 a day per key, shared with MCP. Responses carry `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`; a 429 adds `Retry-After`. The public content endpoints need no key and are limited per client IP instead.


    **Async work.** Research, writing, scans and syncs return as soon as the job is queued; poll `GET /sites/{site}/jobs/{kind}`.


    **Versioning.** `/v1` is frozen for breaking changes; additive changes ship freely.'
  termsOfService: https://blawgy.com/terms
  contact:
    url: https://blawgy.com/developers
servers:
- url: https://app.blawgy.com/v1
security:
- bearerAuth: []
tags:
- name: Existing pages
  description: The inventory of pages that already exist on the site.
paths:
  /sites/{site}/pages/existing:
    get:
      operationId: list_existing_pages
      summary: List existing pages
      description: The pages Blawgy knows the site already has outside the articles Blawgy wrote (found in the sitemap, feeds, Search Console, or imported), with what each page answers when known (ownedIntent, primaryKeyword) and its kind (article, product, category, landing, other, unknown). Includes counts by kind and source and when the inventory last synced. Filter by kind or a search string; page with limit/offset. Free.
      tags:
      - Existing pages
      x-mcp-tool: list_existing_pages
      x-access: read
      x-min-plan: null
      x-partner-only: false
      x-paged: true
      security:
      - bearerAuth: []
      parameters:
      - name: site
        in: path
        required: true
        schema:
          type: string
          minLength: 1
        description: The site, as its domain (example.com). See GET /sites.
      - name: kind
        in: query
        required: false
        description: Only pages of this kind
        schema:
          type: string
          enum:
          - article
          - product
          - category
          - landing
          - other
          - unknown
      - name: search
        in: query
        required: false
        description: Substring match on URL or title
        schema:
          type: string
          maxLength: 200
      - name: limit
        in: query
        required: false
        description: Max pages to return (default 50, max 200) Values above the maximum are clamped to it.
        schema:
          type: integer
          minimum: 1
          maximum: 200
      - name: cursor
        in: query
        required: false
        description: Opaque cursor from a previous page's nextCursor. Omit for the first page.
        schema:
          type: string
      responses:
        '200':
          description: A page of results.
          headers:
            Request-Id:
              $ref: '#/components/headers/Request-Id'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
          content:
            application/json:
              schema:
                type: object
                description: One page. Pass nextCursor as ?cursor= for the next one; null means this was the last page.
                properties:
                  data:
                    type: array
                    items:
                      type: object
                  nextCursor:
                    type:
                    - string
                    - 'null'
                  total:
                    type: integer
                required:
                - data
                - nextCursor
                additionalProperties: true
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
        '403':
          $ref: '#/components/responses/403'
        '404':
          $ref: '#/components/responses/404'
        '429':
          $ref: '#/components/responses/429'
        '500':
          $ref: '#/components/responses/500'
  /sites/{site}/pages/existing/import:
    post:
      operationId: import_existing_pages
      summary: Import existing pages
      description: 'Tell Blawgy about pages and blog posts the customer published BEFORE Blawgy (or outside it), so the content plan never schedules a duplicate article for a search one of them already answers. Up to 500 pages per call; call again for more. Each page is { url, title?, publishedAt? }: url is the full URL on this site (other domains are rejected), title is optional, publishedAt is an optional ISO date. Importing the same URL again updates it. Blawgy then reads each page in the background to work out what it answers (a few minutes). Free. See them with list_existing_pages.'
      tags:
      - Existing pages
      x-mcp-tool: import_existing_pages
      x-access: write
      x-min-plan: null
      x-partner-only: false
      x-async: when-queued
      security:
      - bearerAuth: []
      parameters:
      - name: site
        in: path
        required: true
        schema:
          type: string
          minLength: 1
        description: The site, as its domain (example.com). See GET /sites.
      - $ref: '#/components/parameters/IdempotencyKey'
      - $ref: '#/components/parameters/DryRun'
      responses:
        '200':
          description: The result, exactly what the matching MCP tool returns.
          headers:
            Request-Id:
              $ref: '#/components/headers/Request-Id'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            Idempotent-Replayed:
              $ref: '#/components/headers/Idempotent-Replayed'
          content:
            application/json:
              schema:
                oneOf:
                - type: object
                  additionalProperties: true
                - type: object
                  description: 'With ?dryRun=true: every gate passed, nothing ran.'
                  properties:
                    dryRun:
                      type: boolean
                      const: true
                    tool:
                      type: string
                    summary:
                      type: string
                    valid:
                      type: boolean
                  required:
                  - dryRun
                  - summary
                  - valid
        '202':
          description: 'Accepted: the work was queued and finishes after this response (calls that finish inline answer 200). The body is the same answer the MCP tool gives and says how to follow up: `checkWith` names the call to poll (GET /sites/{site}/jobs/{kind}?id= for get_job, with the `kind` and ids it returns).'
          headers:
            Request-Id:
              $ref: '#/components/headers/Request-Id'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            Idempotent-Replayed:
              $ref: '#/components/headers/Idempotent-Replayed'
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
        '402':
          $ref: '#/components/responses/402'
        '403':
          $ref: '#/components/responses/403'
        '404':
          $ref: '#/components/responses/404'
        '409':
          $ref: '#/components/responses/409'
        '422':
          $ref: '#/components/responses/422'
        '429':
          $ref: '#/components/responses/429'
        '500':
          $ref: '#/components/responses/500'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                pages:
                  type: array
                  items:
                    type: object
                    properties:
                      url:
                        type: string
                        minLength: 1
                        maxLength: 2048
                        description: Full URL of the page on this site, e.g. https://example.com/blog/my-post
                      title:
                        type: string
                        maxLength: 300
                        description: The page title, when known
                      publishedAt:
                        type: string
                        maxLength: 40
                        description: When the page was first published, ISO date (2024-03-01 or 2024-03-01T09:00:00Z)
                    required:
                    - url
                    additionalProperties: false
                  minItems: 1
                  maxItems: 500
                  description: 'Pages to import (1 to 500): url, optional title, optional publishedAt'
              required:
              - pages
              additionalProperties: false
  /sites/{site}/pages/existing/include:
    post:
      operationId: include_existing_page
      summary: Check a skipped page anyway
      description: A page Blawgy skipped (a product, listing, legal or sign-up page, see list_existing_pages kind "skipped") is treated as an article instead, so new plan ideas are checked against it. Blawgy reads the page in the background (a few minutes). Use when a skipped page really is content the plan should not duplicate.
      tags:
      - Existing pages
      x-mcp-tool: include_existing_page
      x-access: write
      x-min-plan: null
      x-partner-only: false
      security:
      - bearerAuth: []
      parameters:
      - name: site
        in: path
        required: true
        schema:
          type: string
          minLength: 1
        description: The site, as its domain (example.com). See GET /sites.
      - $ref: '#/components/parameters/IdempotencyKey'
      - $ref: '#/components/parameters/DryRun'
      responses:
        '200':
          description: The result, exactly what the matching MCP tool returns.
          headers:
            Request-Id:
              $ref: '#/components/headers/Request-Id'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            Idempotent-Replayed:
              $ref: '#/components/headers/Idempotent-Replayed'
          content:
            application/json:
              schema:
                oneOf:
                - type: object
                  additionalProperties: true
                - type: object
                  description: 'With ?dryRun=true: every gate passed, nothing ran.'
                  properties:
                    dryRun:
                      type: boolean
                      const: true
                    tool:
                      type: string
                    summary:
                      type: string
                    valid:
                      type: boolean
                  required:
                  - dryRun
                  - summary
                  - valid
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
        '402':
          $ref: '#/components/responses/402'
        '403':
          $ref: '#/components/responses/403'
        '404':
          $ref: '#/components/responses/404'
        '409':
          $ref: '#/components/responses/409'
        '422':
          $ref: '#/components/responses/422'
        '429':
          $ref: '#/components/responses/429'
        '500':
          $ref: '#/components/responses/500'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                url:
                  type: string
                  minLength: 1
                  maxLength: 2048
                  description: The skipped page URL, as shown by list_existing_pages
              required:
              - url
              additionalProperties: false
  /sites/{site}/pages/existing/remove:
    post:
      operationId: remove_existing_page
      summary: Remove an existing page
      description: Remove one page from the list of existing pages Blawgy keeps for this site (for example a URL imported by mistake, or a page that no longer exists). It stops counting when the plan checks for duplicates. Does not touch the website itself. Import it again to undo.
      tags:
      - Existing pages
      x-mcp-tool: remove_existing_page
      x-access: write
      x-min-plan: null
      x-partner-only: false
      security:
      - bearerAuth: []
      parameters:
      - name: site
        in: path
        required: true
        schema:
          type: string
          minLength: 1
        description: The site, as its domain (example.com). See GET /sites.
      - $ref: '#/components/parameters/IdempotencyKey'
      - $ref: '#/components/parameters/DryRun'
      responses:
        '200':
          description: The result, exactly what the matching MCP tool returns.
          headers:
            Request-Id:
              $ref: '#/components/headers/Request-Id'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            Idempotent-Replayed:
              $ref: '#/components/headers/Idempotent-Replayed'
          content:
            application/json:
              schema:
                oneOf:
                - type: object
                  additionalProperties: true
                - type: object
                  description: 'With ?dryRun=true: every gate passed, nothing ran.'
                  properties:
                    dryRun:
                      type: boolean
                      const: true
                    tool:
                      type: string
                    summary:
                      type: string
                    valid:
                      type: boolean
                  required:
                  - dryRun
                  - summary
                  - valid
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
        '402':
          $ref: '#/components/responses/402'
        '403':
          $ref: '#/components/responses/403'
        '404':
          $ref: '#/components/responses/404'
        '409':
          $ref: '#/components/responses/409'
        '422':
          $ref: '#/components/responses/422'
        '429':
          $ref: '#/components/responses/429'
        '500':
          $ref: '#/components/responses/500'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                url:
                  type: string
                  minLength: 1
                  maxLength: 2048
                  description: The page URL, as shown by list_existing_pages
              required:
              - url
              additionalProperties: false
  /sites/{site}/pages/existing/restore:
    post:
      operationId: restore_existing_page
      summary: Restore a removed existing page
      description: 'Undo remove_existing_page: the page counts again when the plan checks new ideas for duplicates. See removed pages with list_existing_pages kind "removed". Free.'
      tags:
      - Existing pages
      x-mcp-tool: restore_existing_page
      x-access: write
      x-min-plan: null
      x-partner-only: false
      security:
      - bearerAuth: []
      parameters:
      - name: site
        in: path
        required: true
        schema:
          type: string
          minLength: 1
        description: The site, as its domain (example.com). See GET /sites.
      - $ref: '#/components/parameters/IdempotencyKey'
      - $ref: '#/components/parameters/DryRun'
      responses:
        '200':
          description: The result, exactly what the matching MCP tool returns.
          headers:
            Request-Id:
              $ref: '#/components/headers/Request-Id'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            Idempotent-Replayed:
              $ref: '#/components/headers/Idempotent-Replayed'
          content:
            application/json:
              schema:
                oneOf:
                - type: object
                  additionalProperties: true
                - type: object
                  description: 'With ?dryRun=true: every gate passed, nothing ran.'
                  properties:
                    dryRun:
                      type: boolean
                      const: true
                    tool:
                      type: string
                    summary:
                      type: string
                    valid:
                      type: boolean
                  required:
                  - dryRun
                  - summary
                  - valid
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
        '402':
          $ref: '#/components/responses/402'
        '403':
          $ref: '#/components/responses/403'
        '404':
          $ref: '#/components/responses/404'
        '409':
          $ref: '#/components/responses/409'
        '422':
          $ref: '#/components/responses/422'
        '429':
          $ref: '#/components/responses/429'
        '500':
          $ref: '#/components/responses/500'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                url:
                  type: string
                  minLength: 1
                  maxLength: 2048
                  description: The removed page URL, as shown by list_existing_pages kind "removed"
              required:
              - url
              additionalProperties: false
  /sites/{site}/pages/existing/sync:
    post:
      operationId: sync_existing_pages
      summary: Re-scan existing pages
      description: Ask Blawgy to re-read the site's sitemap, feeds and Search Console pages now and update the existing-page list (it also refreshes weekly on its own). Runs in the background for a few minutes; check list_existing_pages after. At most once every 10 minutes per site.
      tags:
      - Existing pages
      x-mcp-tool: sync_existing_pages
      x-access: write
      x-min-plan: null
      x-partner-only: false
      x-async: when-queued
      security:
      - bearerAuth: []
      parameters:
      - name: site
        in: path
        required: true
        schema:
          type: string
          minLength: 1
        description: The site, as its domain (example.com). See GET /sites.
      - $ref: '#/components/parameters/IdempotencyKey'
      - $ref: '#/components/parameters/DryRun'
      responses:
        '200':
          description: The result, exactly what the matching MCP tool returns.
          headers:
            Request-Id:
              $ref: '#/components/headers/Request-Id'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            Idempotent-Replayed:
              $ref: '#/components/headers/Idempotent-Replayed'
          content:
            application/json:
              schema:
                oneOf:
                - type: object
                  additionalProperties: true
                - type: object
                  description: 'With ?dryRun=true: every gate passed, nothing ran.'
                  properties:
                    dryRun:
                      type: boolean
                      const: true
                    tool:
                      type: string
                    summary:
                      type: string
                    valid:
                      type: boolean
                  required:
                  - dryRun
                  - summary
                  - valid
        '202':
          description: 'Accepted: the work was queued and finishes after this response (calls that finish inline answer 200). The body is the same answer the MCP tool gives and says how to follow up: `checkWith` names the call to poll (GET /sites/{site}/jobs/{kind}?id= for get_job, with the `kind` and ids it returns).'
          headers:
            Request-Id:
              $ref: '#/components/headers/Request-Id'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
            Idempotent-Replayed:
              $ref: '#/components/headers/Idempotent-Replayed'
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
        '402':
          $ref: '#/components/responses/402'
        '403':
          $ref: '#/components/responses/403'
        '404':
          $ref: '#/components/responses/404'
        '409':
          $ref: '#/components/responses/409'
        '422':
          $ref: '#/components/responses/422'
        '429':
          $ref: '#/components/responses/429'
        '500':
          $ref: '#/components/responses/500'
components:
  responses:
    '429':
      description: Rate limited; `Retry-After` says when to try again.
      headers:
        Request-Id:
          $ref: '#/components/headers/Request-Id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    '422':
      description: '`idempotency_key_reused`: the Idempotency-Key was used for a different request.'
      headers:
        Request-Id:
          $ref: '#/components/headers/Request-Id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    '402':
      description: The site is read-only until its billing is sorted out.
      headers:
        Request-Id:
          $ref: '#/components/headers/Request-Id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    '401':
      description: The bearer token is missing, unknown, expired or revoked.
      headers:
        Request-Id:
          $ref: '#/components/headers/Request-Id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    '500':
      description: Something failed on our side. The `requestId` finds it in our logs.
      headers:
        Request-Id:
          $ref: '#/components/headers/Request-Id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    '409':
      description: Conflict, including `idempotency_in_progress` and `idempotency_secret_not_replayable` (a retry of a call that returned a one-time secret).
      headers:
        Request-Id:
          $ref: '#/components/headers/Request-Id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    '403':
      description: 'The credential may not do this: read-only key, wrong scope, plan too low (`upgrade_required`), owner only.'
      headers:
        Request-Id:
          $ref: '#/components/headers/Request-Id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    '404':
      description: 'Not found: the route, the site (`site_not_found`) or the thing inside it.'
      headers:
        Request-Id:
          $ref: '#/components/headers/Request-Id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    '400':
      description: The request is malformed or the arguments failed validation (`details.issues` lists them).
      headers:
        Request-Id:
          $ref: '#/components/headers/Request-Id'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      schema:
        type: string
        maxLength: 255
      description: Any unique string (a UUID works). A retry with the same key and request inside 24 hours replays the stored answer instead of running again.
    DryRun:
      name: dryRun
      in: query
      required: false
      schema:
        type: boolean
      description: 'true: run every gate and validation, return a summary, change nothing.'
  headers:
    Request-Id:
      schema:
        type: string
      description: Identifies this request in our logs and audit trail. Quote it to support.
    RateLimit-Remaining:
      schema:
        type: integer
      description: Calls left in the current window.
    RateLimit-Reset:
      schema:
        type: integer
      description: Seconds until the window resets.
    Idempotent-Replayed:
      schema:
        type: boolean
      description: true when this answer was replayed from an earlier request with the same Idempotency-Key.
    RateLimit-Limit:
      schema:
        type: integer
      description: Calls allowed in the current window.
  schemas:
    Error:
      type: object
      required:
      - error
      properties:
        error:
          type: object
          required:
          - code
          - message
          - requestId
          properties:
            code:
              type: string
              description: Stable machine-readable reason (site_not_found, invalid_request, upgrade_required, rate_limited, ...).
            message:
              type: string
            details:
              type: object
              additionalProperties: true
              description: 'Extra context; validation errors carry `issues: [{ path, code, message }]`.'
            requestId:
              type: string
              description: Same as the Request-Id header.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: blk_live_... API key or OAuth access token
      description: An API key from Settings > Account > AI agents in the Blawgy dashboard. Read keys may only call GET endpoints; keys scoped to specific sites cannot reach other sites or change the account.