{
  "openapi": "3.1.0",
  "info": {
    "title": "doc.page API",
    "version": "1.1.0",
    "description": "PDF extraction (Markdown, structured elements, RAG chunks, tables) and tracked Doc Links (publish a PDF as a share link and follow visits, reader companies and per-page reading time). Same engine and account as the doc.page MCP server (https://doc.page/api/mcp)."
  },
  "servers": [
    {
      "url": "https://doc.page"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/api/v1/extract": {
      "post": {
        "operationId": "extractPdf",
        "summary": "Extract a PDF to the canonical ExtractedDocument",
        "description": "Extract a PDF into clean Markdown and structured elements (headings, paragraphs). Returns the canonical ExtractedDocument object. mode \"hybrid\" runs a heavier semantic engine that also reconstructs tables and bounding boxes; the default \"fast\" engine is prose-only (low confidence.tables).",
        "security": [
          {},
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "http(s) URL of the PDF to extract."
                  },
                  "outputs": {
                    "type": "array",
                    "description": "Subset of outputs to include. Default: markdown and elements.",
                    "items": {
                      "type": "string",
                      "enum": [
                        "markdown",
                        "elements",
                        "chunks",
                        "images"
                      ]
                    }
                  },
                  "mode": {
                    "type": "string",
                    "enum": [
                      "fast",
                      "hybrid"
                    ],
                    "description": "fast = prose engine. hybrid = semantic engine with tables + bounding boxes when deployed; falls back to fast with a warning otherwise."
                  },
                  "chunkTokens": {
                    "type": "integer",
                    "description": "Target chunk size in tokens (when chunks are requested). Default 512."
                  }
                },
                "required": [
                  "url"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The canonical ExtractedDocument (docs/10, schemaVersion 1.0).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExtractedDocument"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (bad URL, bad JSON).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Monthly page quota used up and no credits left.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "PDF exceeds the 25 MB limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "Resource is not a PDF.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "424": {
            "description": "The PDF could not be fetched from its origin.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit reached — retry after the indicated seconds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/links": {
      "post": {
        "operationId": "createDocLink",
        "summary": "Publish a PDF as a tracked Doc Link",
        "description": "Publish a PDF as a tracked doc.page Doc Link and get back a shareable URL. The link belongs to the API key's account and also appears in its doc.page library. Requires an API key. Free plan: up to 3 active links; custom vanity slugs are premium-only. Optional expiry and open-notification toggle.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "http(s) URL of the PDF to publish (max 25 MB)."
                  },
                  "name": {
                    "type": "string",
                    "description": "Display name in the library. Defaults to the filename."
                  },
                  "slug": {
                    "type": "string",
                    "description": "Custom vanity slug (premium plans only). Lowercase letters, digits and hyphens."
                  },
                  "expiresAt": {
                    "type": "string",
                    "description": "ISO 8601 date-time after which the link stops working. Omit for no expiry."
                  },
                  "notifyOnOpen": {
                    "type": "boolean",
                    "description": "Email the account owner on the first open. Default true."
                  }
                },
                "required": [
                  "url"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The created link.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocLink"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (bad URL, invalid slug or expiresAt).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key (no anonymous lane on /links).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Free-plan active-link limit reached, or vanity slug requested without premium.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Vanity slug already taken.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "PDF exceeds the 25 MB limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "Resource is not a PDF.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "424": {
            "description": "The PDF could not be fetched from its origin.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit reached (per-key or the shared 40 uploads/hour).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listDocLinks",
        "summary": "List the account’s Doc Links",
        "description": "List the Doc Links of the API key's account (id, slug, URL, name, disabled/expiry state, total views, last view). Use this to recover links created in earlier sessions before querying stats. Requires an API key.",
        "responses": {
          "200": {
            "description": "Up to 100 links, newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocLinkList"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit reached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/links/{id}": {
      "get": {
        "operationId": "getDocLinkStats",
        "summary": "Reading analytics for one Doc Link",
        "description": "Reading analytics for one Doc Link of the API key's account, by id or slug. Always returns the summary (total views, unique visitors, last visit). Premium plans additionally get countries, visitor companies (as_org) and per-page views + average dwell time; pass include:[\"visits\"] for the recent visit rows. Requires an API key.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Doc Link item id OR its public slug (both are accepted).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "include",
            "in": "query",
            "required": false,
            "description": "Set to \"visits\" to include the recent visit rows (enriched on premium plans).",
            "schema": {
              "type": "string",
              "enum": [
                "visits"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Summary always; countries/companies/pages on premium plans.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocLinkStats"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No Doc Link with that id or slug on this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit reached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "revokeDocLink",
        "summary": "Disable a Doc Link (revoke)",
        "description": "Disable a Doc Link of the API key's account (by id or slug) so the public URL stops serving. The item and its stats remain in the library; on the free plan this frees an active-link slot. Requires an API key. Note: send a content-type: application/json header — a DELETE without content-type is rejected (403) by the CSRF layer.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Doc Link item id OR its public slug (both are accepted).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The link is disabled (idempotent).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocLinkRevoked"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No Doc Link with that id or slug on this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit reached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key (dk_live_...). Create one for free at doc.page → account → API keys."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "ExtractedDocument": {
        "type": "object",
        "description": "Canonical extraction object (schemaVersion 1.0): source{engine,pages}, confidence{overall,tables,layout}, markdown, elements[] (type/page/bbox/text/table), optional chunks[] and images[]. Full contract: https://doc.page/en/api/ and src/types/document.ts.",
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "id": {
            "type": "string"
          },
          "source": {
            "type": "object"
          },
          "confidence": {
            "type": "object"
          },
          "title": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "markdown": {
            "type": "string"
          },
          "elements": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "chunks": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "images": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "schemaVersion",
          "id",
          "source",
          "confidence",
          "markdown",
          "elements"
        ]
      },
      "DocLink": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "link": {
            "type": "string",
            "description": "Public URL: https://doc.page/d/<slug>"
          },
          "name": {
            "type": "string"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "slug",
          "link",
          "name"
        ]
      },
      "DocLinkList": {
        "type": "object",
        "properties": {
          "links": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "slug": {
                  "type": "string"
                },
                "link": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "disabled": {
                  "type": "boolean"
                },
                "expiresAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "createdAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "sizeBytes": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "totalViews": {
                  "type": "integer"
                },
                "lastViewAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                }
              },
              "required": [
                "id",
                "slug",
                "link",
                "name",
                "disabled",
                "createdAt",
                "totalViews"
              ]
            }
          }
        },
        "required": [
          "links"
        ]
      },
      "DocLinkStats": {
        "type": "object",
        "description": "Summary is always present. countries/companies/pages only on premium plans; visits only with ?include=visits.",
        "properties": {
          "id": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "link": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "plan": {
            "type": "string",
            "enum": [
              "free",
              "pro"
            ]
          },
          "disabled": {
            "type": "boolean"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "totalViews": {
            "type": "integer"
          },
          "visitors": {
            "type": "integer"
          },
          "lastVisit": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "countries": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "country": {
                  "type": "string"
                },
                "visits": {
                  "type": "integer"
                }
              }
            }
          },
          "companies": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "company": {
                  "type": "string"
                },
                "visits": {
                  "type": "integer"
                }
              }
            }
          },
          "pages": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "page": {
                  "type": "integer"
                },
                "views": {
                  "type": "integer"
                },
                "avgMs": {
                  "type": "integer"
                }
              }
            }
          },
          "visits": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "upgradeNote": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "slug",
          "link",
          "name",
          "plan",
          "disabled",
          "totalViews",
          "visitors"
        ]
      },
      "DocLinkRevoked": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "disabled": {
            "type": "boolean",
            "const": true
          }
        },
        "required": [
          "id",
          "slug",
          "disabled"
        ]
      }
    }
  }
}