{
  "openapi": "3.1.0",
  "info": {
    "title": "Paper — public web endpoints",
    "version": "1.0.0",
    "summary": "Public HTTP endpoints served by paper.design.",
    "description": "Paper's integration surface for AI agents is the Paper MCP server, not a REST API — see https://paper.design/docs/mcp for the Model Context Protocol server that lets agents read and write designs directly. This specification covers the small set of unauthenticated endpoints served by the paper.design website itself. The authenticated product API at api.paper.design is not public and is not described here.",
    "contact": {
      "name": "Paper",
      "url": "https://paper.design/docs/support"
    },
    "license": {
      "name": "Proprietary",
      "identifier": "LicenseRef-Paper"
    }
  },
  "servers": [
    {
      "url": "https://paper.design",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "url": "https://paper.design/docs",
    "description": "Paper documentation"
  },
  "security": [],
  "tags": [
    {
      "name": "Status",
      "description": "Service messages surfaced inside the Paper desktop app."
    },
    {
      "name": "Purchase",
      "description": "Redirect endpoints that hand off to Stripe Checkout."
    }
  ],
  "paths": {
    "/status/app-message": {
      "get": {
        "operationId": "getAppMessage",
        "summary": "Get the active app message",
        "description": "Returns the service message the Paper desktop app displays in a modal, or `null` when no message is active. Public and CORS-enabled (`Access-Control-Allow-Origin: *`); no authentication required.",
        "tags": ["Status"],
        "responses": {
          "200": {
            "description": "The active app message, or `null` when none is set.",
            "headers": {
              "Access-Control-Allow-Origin": {
                "description": "Always `*`.",
                "schema": { "type": "string" }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/AppMessage" },
                    { "type": "null" }
                  ]
                },
                "examples": {
                  "active": {
                    "summary": "A message is being shown",
                    "value": {
                      "title": "System maintenance",
                      "message": "Planning to return by 10AM Pacific",
                      "expiration": 1761764400000
                    }
                  },
                  "none": {
                    "summary": "No message is active",
                    "value": null
                  }
                }
              }
            }
          }
        }
      },
      "options": {
        "operationId": "preflightAppMessage",
        "summary": "CORS preflight",
        "tags": ["Status"],
        "responses": {
          "200": {
            "description": "Preflight response. Body is empty.",
            "headers": {
              "Access-Control-Allow-Origin": { "schema": { "type": "string" } },
              "Access-Control-Allow-Methods": { "schema": { "type": "string" } },
              "Access-Control-Allow-Headers": { "schema": { "type": "string" } }
            }
          }
        }
      }
    },
    "/purchase": {
      "get": {
        "operationId": "startPurchase",
        "summary": "Begin a purchase",
        "description": "Redirects to the Paper sign-in flow, which returns to `/purchase/{priceKey}` once the visitor is authenticated. Intended for browsers, not for programmatic use.",
        "tags": ["Purchase"],
        "parameters": [
          {
            "name": "priceKey",
            "in": "query",
            "required": false,
            "description": "Identifier of the price to purchase. Forwarded to the post-sign-in redirect.",
            "schema": { "type": "string", "default": "" }
          }
        ],
        "responses": {
          "307": {
            "description": "Redirect to the sign-in page.",
            "headers": {
              "Location": {
                "description": "Absolute sign-in URL carrying `final_redirect_uri`.",
                "schema": { "type": "string", "format": "uri" }
              }
            }
          }
        }
      }
    },
    "/purchase/{priceKey}": {
      "get": {
        "operationId": "createCheckoutSession",
        "summary": "Create a Stripe Checkout session and redirect to it",
        "description": "Creates a Stripe Checkout session for the given price and redirects to Stripe. Requires the caller's Paper session cookie, which is forwarded upstream; without it the upstream call fails and the endpoint responds `400`.",
        "tags": ["Purchase"],
        "parameters": [
          {
            "name": "priceKey",
            "in": "path",
            "required": true,
            "description": "Identifier of the price to purchase.",
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "307": {
            "description": "Redirect to Stripe Checkout.",
            "headers": {
              "Location": {
                "description": "Stripe Checkout session URL.",
                "schema": { "type": "string", "format": "uri" }
              }
            }
          },
          "400": {
            "description": "No checkout session could be created for the given price key.",
            "content": {
              "text/plain": {
                "schema": { "type": "string" },
                "example": "Could not create a checkout session for: pro-monthly."
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AppMessage": {
        "type": "object",
        "title": "AppMessage",
        "description": "A modal message displayed inside the Paper desktop app.",
        "required": ["title", "message", "expiration"],
        "additionalProperties": false,
        "properties": {
          "title": {
            "type": "string",
            "description": "The modal title displayed to the user.",
            "examples": ["System maintenance"]
          },
          "message": {
            "type": "string",
            "description": "A detailed message displayed as smaller text inside the modal.",
            "examples": ["Planning to return by 10AM Pacific"]
          },
          "expiration": {
            "type": "integer",
            "format": "int64",
            "description": "Unix timestamp in milliseconds, UTC. The app stops showing the message after this instant.",
            "examples": [1761764400000]
          }
        }
      }
    }
  }
}
