Onto Extract API

Return the structured data a page declares (JSON-LD, OpenGraph, meta). Deterministic, no AI.

Operations 1

POST /v1/extract Extract a page's structured data #

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/buildonto-dev:buildonto-dev-extract-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

buildonto-dev-extract-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Onto Read Extract API
  version: 1.0.0
  summary: Turn any URL into clean Markdown, an AIO accuracy score, and hallucination-risk flags.
  description: 'The Onto Read API takes a URL and returns clean Markdown that an LLM can consume directly,

    plus a 0–100 AIO accuracy score and hallucination-risk metadata.


    **Authentication.** All requests use bearer-token auth — pass your API key in the

    `Authorization` header. Get one at app.buildonto.dev/read/keys;

    the Free tier gives you 1,000 credits a month.


    **Endpoints.** `/v1/read`, `/v1/score`, `/v1/read-and-score` and `/v1/extract` work on one

    URL. `/v1/batch` handles up to 50 URLs in one call, `/v1/map` lists a site''s URLs, and

    `/v1/usage` shows your quota and credits. Most agent workflows want `/v1/read-and-score` —

    it returns both the cleaned Markdown and the accuracy metadata in a single round-trip.


    **Credits.** `/v1/read`, `/v1/read-and-score`, `/v1/extract` and `/v1/map` cost 1 credit per

    call; `/v1/batch` costs 1 credit per URL. `/v1/score` and `/v1/usage` are free. Failed

    requests are refunded.


    **Errors.** Every error response shares the same shape with a stable `code` field — branch

    on `code`, not on the human-readable `message`. Extra details, like `retry_after`, sit at

    the top level of the body. See

    the error codes index for the full catalog.'
  contact:
    name: Onto support
    email: founder@buildonto.dev
    url: https://buildonto.dev
  license:
    name: Proprietary
    url: https://buildonto.dev/legal/terms
servers:
- url: https://api.buildonto.dev
  description: Production
security:
- bearerAuth: []
tags:
- name: Extract
  description: Return the structured data a page declares (JSON-LD, OpenGraph, meta). Deterministic, no AI.
paths:
  /v1/extract:
    post:
      tags:
      - Extract
      summary: Extract a page's structured data
      operationId: extract
      description: 'Returns the structured data the page already declares — JSON-LD, OpenGraph, and meta

        tags — plus the AIO trust score. Deterministic; no fields are inferred by a model.

        Costs 1 credit. For a PDF or plain-text URL, `aio_score`, `grade` and

        `hallucination_risk` are null.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - url
              properties:
                url:
                  type: string
                  format: uri
                fresh:
                  type: boolean
                  default: false
            examples:
              basic:
                value:
                  url: https://vercel.com
      responses:
        '200':
          description: Structured data extracted
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  url:
                    type: string
                  title:
                    type: string
                  aio_score:
                    type:
                    - integer
                    - 'null'
                  grade:
                    type:
                    - string
                    - 'null'
                  hallucination_risk:
                    type:
                    - string
                    - 'null'
                    enum:
                    - low
                    - medium
                    - high
                    - null
                  structured:
                    type: object
                    properties:
                      jsonLd:
                        type: array
                        items:
                          type: object
                      openGraph:
                        type: object
                        additionalProperties:
                          type: string
                      meta:
                        type: object
                        additionalProperties:
                          type: string
                  counts:
                    type: object
                  cache:
                    type: object
              example:
                status: success
                url: https://vercel.com
                title: 'Vercel: Build and deploy…'
                aio_score: 90
                grade: Excellent
                hallucination_risk: low
                structured:
                  jsonLd:
                  - '@type': SoftwareApplication
                    name: Vercel
                  openGraph:
                    og:title: Vercel…
                    og:type: website
                  meta:
                    description: Vercel provides…
                counts:
                  json_ld: 1
                  open_graph: 13
                  meta: 10
                cache:
                  hit: false
                  ttl_seconds: 3600
        '400':
          $ref: '#/components/responses/InvalidUrl'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/UrlNotFound'
        '413':
          $ref: '#/components/responses/TooLarge'
        '415':
          $ref: '#/components/responses/UnsupportedType'
        '422':
          $ref: '#/components/responses/ImagePdf'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/ExtractionFailed'
        '502':
          $ref: '#/components/responses/TlsError'
        '504':
          $ref: '#/components/responses/Timeout'
components:
  responses:
    UnsupportedType:
      description: '`UNSUPPORTED_TYPE` — the URL isn''t HTML, PDF or text (for example an image, video or archive).'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            status: error
            code: UNSUPPORTED_TYPE
            message: Not a readable document (image/png). Onto reads HTML, PDF, and text formats.
    Forbidden:
      description: 'Multiple causes:

        - `WAF_BLOCKED` — target site refused our crawler (origin returned 401/403)

        - `ROBOTS_BLOCKED` — target site''s robots.txt has `Disallow: /` for GPTBot or `*`

        '
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            waf:
              value:
                status: error
                code: WAF_BLOCKED
                message: Target site refused our crawler (HTTP 403)
            robots:
              value:
                status: error
                code: ROBOTS_BLOCKED
                message: Target site's robots.txt disallows AI crawlers. We honor robots.txt — see https://buildonto.dev/about-bot.
    Timeout:
      description: Target site took longer than 15 seconds to respond.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            status: error
            code: TIMEOUT
            message: Target site took too long to respond
    UrlNotFound:
      description: Target URL returned 404, or its hostname doesn't resolve.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            status: error
            code: URL_NOT_FOUND
            message: 'Target URL returned 404: https://example.com/old-page'
    PaymentRequired:
      description: Paid plans only — monthly plan credits AND bought credits are both used up. Free gets `RATE_LIMITED` instead.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            status: error
            code: PAYMENT_REQUIRED
            message: Monthly plan quota exceeded and credit balance is empty. Top up credits in the dashboard to continue.
            plan_limit: 10000
            credits_remaining: 0
    TlsError:
      description: '`TLS_ERROR` — the target site''s TLS certificate or handshake failed.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            status: error
            code: TLS_ERROR
            message: Target site has an invalid TLS certificate (CERT_HAS_EXPIRED)
    TooLarge:
      description: '`TOO_LARGE` — the document is over 10 MB.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            status: error
            code: TOO_LARGE
            message: Document exceeds the read limit; Onto reads up to 10MB
    ImagePdf:
      description: '`IMAGE_PDF` — a scanned PDF with no text layer. Onto does not OCR.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            status: error
            code: IMAGE_PDF
            message: This PDF has no extractable text (likely scanned or image-only). Onto does not OCR.
    Unauthorized:
      description: Missing, malformed, or revoked Bearer token.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            status: error
            code: UNAUTHORIZED
            message: Missing or invalid API key
    InvalidUrl:
      description: '`INVALID_URL` — body isn''t JSON, `url` is missing or unparseable, the scheme isn''t

        http(s), or the URL points at a private or internal host.

        '
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            status: error
            code: INVALID_URL
            message: '"url" field is required'
    ExtractionFailed:
      description: '`EXTRACTION_FAILED` — the origin returned an error status other than 401/403/404, the

        host refused the connection or was unreachable, there were more than 5 redirects or a

        bad redirect, or the page or PDF couldn''t be parsed. Retry once; errors are never cached.

        '
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            status: error
            code: EXTRACTION_FAILED
            message: Upstream returned HTTP 503
    RateLimited:
      description: 'Multiple causes:

        - `RATE_LIMITED` — monthly plan credits used up (Free only; paid plans spill into bought credits)

        - `CONCURRENT_LIMIT` — too many requests running at once for your plan; retry after 1 second

        '
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            monthly:
              value:
                status: error
                code: RATE_LIMITED
                message: Monthly quota exceeded
                retry_after: '2026-10-01T00:00:00.000Z'
            concurrent:
              value:
                status: error
                code: CONCURRENT_LIMIT
                message: Too many concurrent requests for your tier (5/5 in flight). Retry in a moment.
                in_flight: 5
                limit: 5
                retry_after: 1
  schemas:
    ErrorResponse:
      type: object
      required:
      - status
      - code
      - message
      properties:
        status:
          type: string
          enum:
          - error
        code:
          type: string
          description: Stable error code — branch on this, not on `message`.
        message:
          type: string
          description: Human-readable message; wording may change without notice.
        retry_after:
          oneOf:
          - type: integer
            description: Seconds to wait before retrying (CONCURRENT_LIMIT). Always 1.
          - type: string
            format: date-time
            description: When monthly credits reset — the end of the current UTC month (RATE_LIMITED).
        plan_limit:
          type: integer
          description: Your plan's monthly credits (PAYMENT_REQUIRED).
        credits_remaining:
          type: integer
          description: Bought credits left, always 0 (PAYMENT_REQUIRED).
        in_flight:
          type: integer
          description: Requests running for your account right now (CONCURRENT_LIMIT).
        limit:
          type: integer
          description: Your plan's concurrency limit (CONCURRENT_LIMIT).
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: onto_sk_live_…
      description: 'Pass your API key as `Authorization: Bearer {your_key}`. Get a key at

        [app.buildonto.dev/read/keys](https://app.buildonto.dev/read/keys).

        '