{
  "openapi": "3.1.0",
  "info": {
    "title": "Papermill API",
    "description": "Generate PDFs from Press documents, Markdown, JSON, and CSV. Full documentation is at https://docs.papermill.io/api/.",
    "version": "2.0.0",
    "contact": {
      "name": "Papermill Support",
      "email": "support@papermill.io",
      "url": "https://docs.papermill.io"
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "required": ["statusCode", "message", "timestamp"],
        "properties": {
          "statusCode": {
            "type": "integer",
            "description": "Repeats the HTTP status."
          },
          "message": {
            "type": "string",
            "description": "Human-readable description. May be reworded — branch on `data.code` instead."
          },
          "timestamp": {
            "type": "string",
            "description": "When the failure occurred."
          },
          "stackTrace": {
            "type": "array",
            "description": "Source locations responsible, on Press authoring errors.",
            "items": {
              "type": "object"
            }
          },
          "data": {
            "type": "object",
            "description": "Machine-readable detail. Present on known failure modes.",
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable identifier for the failure mode.",
                "enum": [
                  "ERR_EMAIL_NOT_VERIFIED",
                  "ERR_ACCOUNT_DISABLED",
                  "ERR_QUOTA_EXCEEDED",
                  "ERR_DRAFT_QUOTA_EXCEEDED",
                  "ERR_RENDER_TIMEOUT",
                  "ERR_TEMPLATE_NOT_FOUND",
                  "ERR_TEMPLATE_EMPTY",
                  "ERR_RATE_LIMITED",
                  "ERR_SLUG_TAKEN",
                  "ERR_SLUG_INVALID",
                  "ERR_SLUG_NOT_ASSIGNED",
                  "ERR_WORKSPACE_UNRESOLVED",
                  "ERR_KEY_REVOKED",
                  "ERR_KEY_EXPIRED"
                ]
              },
              "cap": {
                "type": "number",
                "description": "Page allowance, on quota failures."
              },
              "usage": {
                "type": "number",
                "description": "Pages used so far, on quota failures."
              }
            }
          }
        }
      }
    },
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Your Papermill API key, sent as `Authorization: Bearer <key>`."
      },
      "ApiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Your Papermill API key. Equivalent to the bearer form."
      }
    }
  },
  "paths": {
    "/v2/authcheck": {
      "get": {
        "operationId": "authcheck",
        "summary": "Verify an API key",
        "tags": ["Account"],
        "description": "Confirms the presented API key is usable and names the account it belongs to. Takes no parameters and no body.",
        "responses": {
          "200": {
            "description": "The key is usable.",
            "content": {
              "application/json": {
                "schema": {
                  "description": "The key is usable.",
                  "type": "object",
                  "required": ["status"],
                  "properties": {
                    "status": {
                      "type": "string",
                      "description": "Confirmation naming the authenticated account."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unrecognised, revoked, or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account is disabled, or the email address is unverified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Honour the `Retry-After` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v2/validate": {
      "post": {
        "operationId": "validate",
        "summary": "Validate a payload",
        "tags": ["Documents"],
        "description": "Reports syntax and semantic problems in a payload without rendering it. A 200 response does not mean the payload is valid — read `valid`. Takes the same body and content types as `POST /v2/pdf`.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "query",
            "name": "template_id",
            "required": false,
            "description": "The template to render or validate against. Required when the body is JSON, CSV, or Markdown; optional when the body is a complete Press document.\n\nAdd an `@` suffix to pin the content: `report@3` for a published version, `report@latest` for the newest, `report@<tag>` for the version a tag names, or `report@live` for the current content, which is also what a bare identifier renders.",
            "examples": {
              "papermill-invoice": {
                "value": "papermill-invoice"
              },
              "papermill-modern-invoice": {
                "value": "papermill-modern-invoice"
              },
              "papermill-modern-letter": {
                "value": "papermill-modern-letter"
              },
              "papermill-modern-report": {
                "value": "papermill-modern-report"
              },
              "papermill-simple-report": {
                "value": "papermill-simple-report"
              }
            }
          },
          {
            "schema": {
              "type": "string"
            },
            "in": "query",
            "name": "flow",
            "required": false,
            "description": "With `Content-Type: text/markdown`, the template flow the body replaces. Defaults to `body`. Supplying it with any other content type is rejected rather than silently ignored."
          }
        ],
        "responses": {
          "200": {
            "description": "Validation findings, split by severity.",
            "content": {
              "application/json": {
                "schema": {
                  "description": "Validation findings, split by severity.",
                  "type": "object",
                  "required": ["valid", "errors", "warnings"],
                  "properties": {
                    "valid": {
                      "type": "boolean",
                      "description": "True when `errors` is empty."
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "message": {
                            "type": "string",
                            "description": "What is wrong."
                          },
                          "source": {
                            "type": "object",
                            "description": "Where the finding sits. Absent when it cannot be tied to a position.",
                            "properties": {
                              "tagName": {
                                "type": "string",
                                "description": "The element the finding sits on."
                              },
                              "origin": {
                                "type": "string",
                                "enum": ["template", "payload"],
                                "description": "Which document the finding is in. Present only when `template_id` was supplied."
                              },
                              "lineStart": {
                                "type": "number",
                                "description": "First line of the element."
                              },
                              "lineEnd": {
                                "type": "number",
                                "description": "Last line of the element."
                              },
                              "columnStart": {
                                "type": "number",
                                "description": "First column of the element."
                              },
                              "columnEnd": {
                                "type": "number",
                                "description": "Last column of the element."
                              }
                            }
                          }
                        }
                      },
                      "description": "Findings that prevent rendering."
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "message": {
                            "type": "string",
                            "description": "What is wrong."
                          },
                          "source": {
                            "type": "object",
                            "description": "Where the finding sits. Absent when it cannot be tied to a position.",
                            "properties": {
                              "tagName": {
                                "type": "string",
                                "description": "The element the finding sits on."
                              },
                              "origin": {
                                "type": "string",
                                "enum": ["template", "payload"],
                                "description": "Which document the finding is in. Present only when `template_id` was supplied."
                              },
                              "lineStart": {
                                "type": "number",
                                "description": "First line of the element."
                              },
                              "lineEnd": {
                                "type": "number",
                                "description": "Last line of the element."
                              },
                              "columnStart": {
                                "type": "number",
                                "description": "First column of the element."
                              },
                              "columnEnd": {
                                "type": "number",
                                "description": "Last column of the element."
                              }
                            }
                          }
                        }
                      },
                      "description": "Findings that do not prevent rendering."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request or the document is malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unrecognised, revoked, or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account is disabled, or the email address is unverified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "The template, version, or tag does not exist, or is not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The request body exceeded 32 MB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "The `Content-Type` is not one Papermill accepts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Honour the `Retry-After` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "description": "A complete Press document, or data to merge into `template_id`. How the body is read depends on the `Content-Type`: the XML types are a whole document, while JSON and CSV supply data and Markdown supplies flow content. Bodies are capped at 32 MB.",
          "required": true,
          "content": {
            "text/xml": {
              "examples": {
                "Press": {
                  "summary": "A Press document",
                  "value": "<press>\n  <document format=\"A4\">\n    <page>Hello</page>\n  </document>\n</press>",
                  "lang": "xml",
                  "isAutogenerated": true
                }
              }
            },
            "application/xml": {
              "examples": {
                "Press": {
                  "summary": "A Press document",
                  "value": "<press>\n  <document format=\"A4\">\n    <page>Hello</page>\n  </document>\n</press>",
                  "lang": "xml",
                  "isAutogenerated": true
                }
              }
            },
            "text/plain": {
              "examples": {
                "Press": {
                  "summary": "A Press document",
                  "value": "<press>\n  <document format=\"A4\">\n    <page>Hello</page>\n  </document>\n</press>",
                  "lang": "xml",
                  "isAutogenerated": true
                }
              }
            },
            "application/json": {
              "schema": {
                "type": "object"
              }
            },
            "text/csv": {
              "schema": {
                "type": "string"
              }
            },
            "text/markdown": {
              "schema": {
                "type": "string"
              }
            }
          }
        }
      }
    },
    "/v2/pdf": {
      "post": {
        "operationId": "generatePDF",
        "summary": "Render a PDF",
        "tags": ["Documents"],
        "description": "Renders a PDF from a complete Press document, or from data merged into the template named by `template_id`. The response body is the PDF itself.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "query",
            "name": "template_id",
            "required": false,
            "description": "The template to render or validate against. Required when the body is JSON, CSV, or Markdown; optional when the body is a complete Press document.\n\nAdd an `@` suffix to pin the content: `report@3` for a published version, `report@latest` for the newest, `report@<tag>` for the version a tag names, or `report@live` for the current content, which is also what a bare identifier renders.",
            "examples": {
              "papermill-invoice": {
                "value": "papermill-invoice"
              },
              "papermill-modern-invoice": {
                "value": "papermill-modern-invoice"
              },
              "papermill-modern-letter": {
                "value": "papermill-modern-letter"
              },
              "papermill-modern-report": {
                "value": "papermill-modern-report"
              },
              "papermill-simple-report": {
                "value": "papermill-simple-report"
              }
            }
          },
          {
            "schema": {
              "type": "string"
            },
            "in": "query",
            "name": "flow",
            "required": false,
            "description": "With `Content-Type: text/markdown`, the template flow the body replaces. Defaults to `body`. Supplying it with any other content type is rejected rather than silently ignored."
          },
          {
            "schema": {
              "type": "string"
            },
            "in": "query",
            "name": "draft",
            "required": false,
            "description": "Set to `true` to render against your draft allowance instead of your production page allowance. Any other value renders against the production allowance."
          }
        ],
        "responses": {
          "200": {
            "description": "The rendered PDF.",
            "headers": {
              "Content-Type": {
                "schema": {
                  "type": "string",
                  "default": "application/pdf"
                }
              },
              "Content-Disposition": {
                "schema": {
                  "type": "string",
                  "default": "inline; filename=\"example.pdf\""
                }
              }
            },
            "content": {
              "application/pdf": {
                "schema": {
                  "description": "The rendered PDF.",
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "The request or the document is malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unrecognised, revoked, or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "The page allowance for the billing period is used up.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account is disabled, or the email address is unverified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "The template, version, or tag does not exist, or is not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The request body exceeded 32 MB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "The `Content-Type` is not one Papermill accepts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Honour the `Retry-After` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "504": {
            "description": "The render exceeded the time budget.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "description": "A complete Press document, or data to merge into `template_id`. How the body is read depends on the `Content-Type`: the XML types are a whole document, while JSON and CSV supply data and Markdown supplies flow content. Bodies are capped at 32 MB.",
          "required": true,
          "content": {
            "text/xml": {
              "examples": {
                "Press": {
                  "summary": "A Press document",
                  "value": "<press>\n  <document format=\"A4\">\n    <page>Hello</page>\n  </document>\n</press>",
                  "lang": "xml",
                  "isAutogenerated": true
                }
              }
            },
            "application/xml": {
              "examples": {
                "Press": {
                  "summary": "A Press document",
                  "value": "<press>\n  <document format=\"A4\">\n    <page>Hello</page>\n  </document>\n</press>",
                  "lang": "xml",
                  "isAutogenerated": true
                }
              }
            },
            "text/plain": {
              "examples": {
                "Press": {
                  "summary": "A Press document",
                  "value": "<press>\n  <document format=\"A4\">\n    <page>Hello</page>\n  </document>\n</press>",
                  "lang": "xml",
                  "isAutogenerated": true
                }
              }
            },
            "application/json": {
              "schema": {
                "type": "object"
              }
            },
            "text/csv": {
              "schema": {
                "type": "string"
              }
            },
            "text/markdown": {
              "schema": {
                "type": "string"
              }
            }
          }
        }
      }
    },
    "/v2/account/usage": {
      "get": {
        "operationId": "accountUsage",
        "summary": "Read account usage",
        "tags": ["Account"],
        "description": "Reports page and request consumption for the current billing period. The period runs from your plan renewal day, so it is usually not a calendar month.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "query",
            "name": "date",
            "required": false,
            "description": "A date inside the billing period to report on. Defaults to the current period."
          }
        ],
        "responses": {
          "200": {
            "description": "Consumption for the billing period.",
            "content": {
              "application/json": {
                "schema": {
                  "description": "Consumption for the billing period.",
                  "type": "object",
                  "required": ["pagesGenerated", "apiCalls", "maxPagesGenerated", "startDate", "endDate"],
                  "properties": {
                    "pagesGenerated": {
                      "type": "number",
                      "description": "Production pages generated this period."
                    },
                    "apiCalls": {
                      "type": "number",
                      "description": "Requests made this period."
                    },
                    "maxPagesGenerated": {
                      "type": "number",
                      "description": "Production page allowance for the plan."
                    },
                    "startDate": {
                      "type": "string",
                      "description": "Start of the billing period."
                    },
                    "endDate": {
                      "type": "string",
                      "description": "End of the billing period."
                    },
                    "draft": {
                      "type": "object",
                      "description": "Draft consumption. Appears after the first draft render of the period.",
                      "properties": {
                        "pagesGenerated": {
                          "type": "number",
                          "description": "Draft pages generated this period."
                        },
                        "apiCalls": {
                          "type": "number",
                          "description": "Draft requests made this period."
                        }
                      }
                    },
                    "maxDraftPagesGenerated": {
                      "type": "number",
                      "description": "Draft page allowance, on plans that set one."
                    },
                    "overagePages": {
                      "type": "number",
                      "description": "Pages generated beyond the allowance."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unrecognised, revoked, or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account is disabled, or the email address is unverified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Honour the `Retry-After` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v2/slugs": {
      "post": {
        "operationId": "createTemplateSlug",
        "summary": "Assign a slug to a template",
        "tags": ["Slugs"],
        "description": "Gives a template a human-readable name that can be used in place of its id. A slug is unique within your workspace, and a template holds at most one: assigning a second one releases the first. Re-assigning a slug the template already holds succeeds unchanged.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["slug", "template_id"],
                "additionalProperties": false,
                "properties": {
                  "slug": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 64,
                    "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
                  },
                  "template_id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 128,
                    "pattern": "^(?!__.*__$)[A-Za-z0-9_-]+$",
                    "description": "The template's id. Another slug is not accepted here, only the id itself."
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Slug assigned",
            "content": {
              "application/json": {
                "schema": {
                  "description": "Slug assigned",
                  "type": "object",
                  "properties": {
                    "slug": {
                      "type": "string"
                    },
                    "template_id": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request is malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unrecognised, revoked, or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account is disabled, or the email address is unverified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "The template does not exist, or is not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A different template already holds the slug, or the account belongs to no workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The request body exceeded 32 MB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "The `Content-Type` is not one Papermill accepts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Honour the `Retry-After` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listTemplateSlugs",
        "summary": "List assigned slugs",
        "tags": ["Slugs"],
        "description": "Every slug assigned in your workspace, with the template each one names. A workspace holds at most one slug per template, so the listing is capped at 1000 and there is no cursor: a workspace with more templates than that would need one added before the listing could be read as complete.",
        "responses": {
          "200": {
            "description": "Assigned slugs",
            "content": {
              "application/json": {
                "schema": {
                  "description": "Assigned slugs",
                  "type": "object",
                  "properties": {
                    "slugs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "slug": {
                            "type": "string"
                          },
                          "template_id": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unrecognised, revoked, or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account is disabled, or the email address is unverified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The account belongs to no workspace, so slugs are unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Honour the `Retry-After` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v2/slugs/{slug}": {
      "get": {
        "operationId": "getTemplateSlug",
        "summary": "Check whether a slug is available",
        "tags": ["Slugs"],
        "description": "Reports whether a slug is free to assign in your workspace, and which template it names when it is already taken. A slug that breaks the naming rules is reported as invalid rather than as available.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 64,
              "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
            },
            "in": "path",
            "name": "slug",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Slug status",
            "content": {
              "application/json": {
                "schema": {
                  "description": "Slug status",
                  "type": "object",
                  "properties": {
                    "slug": {
                      "type": "string"
                    },
                    "available": {
                      "type": "boolean"
                    },
                    "template_id": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request is malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unrecognised, revoked, or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account is disabled, or the email address is unverified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The account belongs to no workspace, so slugs are unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Honour the `Retry-After` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteTemplateSlug",
        "summary": "Release a slug",
        "tags": ["Slugs"],
        "description": "Releases a slug so it can be assigned again. A slug can be released even when the template it named is no longer available.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 64,
              "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
            },
            "in": "path",
            "name": "slug",
            "required": true
          }
        ],
        "responses": {
          "204": {
            "description": "Slug released"
          },
          "400": {
            "description": "The request is malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unrecognised, revoked, or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account is disabled, or the email address is unverified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "The slug is not assigned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The account belongs to no workspace, so slugs are unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Honour the `Retry-After` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v2/templates/{templateId}/versions": {
      "post": {
        "operationId": "createTemplateVersion",
        "summary": "Publish a version of a template",
        "tags": ["Versions & Tags"],
        "description": "Stores a read-only snapshot of the template's current content and returns the version number it was given, with 201. Numbers start at 1 and count up. The optional `message` records what changed. Publishing content identical to the newest version stores nothing and answers 200 with that existing version, under the message it was already published with — a message sent alongside unchanged content is discarded.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "message": {
                    "type": "string",
                    "maxLength": 500
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^(?!__.*__$)[A-Za-z0-9_-]+$"
            },
            "in": "path",
            "name": "templateId",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Content unchanged; the version that already held it",
            "content": {
              "application/json": {
                "schema": {
                  "description": "Content unchanged; the version that already held it",
                  "type": "object",
                  "properties": {
                    "version": {
                      "type": "integer"
                    },
                    "sha256": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string"
                    },
                    "created_by": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "email": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Version published",
            "content": {
              "application/json": {
                "schema": {
                  "description": "Version published",
                  "type": "object",
                  "properties": {
                    "version": {
                      "type": "integer"
                    },
                    "sha256": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string"
                    },
                    "created_by": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "email": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request is malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unrecognised, revoked, or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account is disabled, or the email address is unverified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "The template, version, or tag does not exist, or is not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The template's content is too large to publish, or the request body exceeded 32 MB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "The `Content-Type` is not one Papermill accepts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Honour the `Retry-After` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listTemplateVersions",
        "summary": "List a template's versions",
        "tags": ["Versions & Tags"],
        "description": "A template's published versions, newest first and without their content. `has_more` is true when the template holds versions older than the last one returned; those are read one at a time by number, since numbers count up from 1 with no gaps.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^(?!__.*__$)[A-Za-z0-9_-]+$"
            },
            "in": "path",
            "name": "templateId",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Published versions",
            "content": {
              "application/json": {
                "schema": {
                  "description": "Published versions",
                  "type": "object",
                  "properties": {
                    "versions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "version": {
                            "type": "integer"
                          },
                          "sha256": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          },
                          "created_at": {
                            "type": "string"
                          },
                          "created_by": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              },
                              "email": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request is malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unrecognised, revoked, or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account is disabled, or the email address is unverified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "The template, version, or tag does not exist, or is not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Honour the `Retry-After` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v2/templates/{templateId}/versions/{version}": {
      "get": {
        "operationId": "getTemplateVersion",
        "summary": "Read one version of a template",
        "tags": ["Versions & Tags"],
        "description": "Returns a published version and its content. The content carries a header comment naming the version, the time it was published, who published it, and the sha256 of the content below the header — remove the header and hash what remains to check it.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^(?!__.*__$)[A-Za-z0-9_-]+$"
            },
            "in": "path",
            "name": "templateId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 16
            },
            "in": "path",
            "name": "version",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "The published version",
            "content": {
              "application/json": {
                "schema": {
                  "description": "The published version",
                  "type": "object",
                  "properties": {
                    "version": {
                      "type": "integer"
                    },
                    "sha256": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string"
                    },
                    "created_by": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "email": {
                          "type": "string"
                        }
                      }
                    },
                    "content": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request is malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unrecognised, revoked, or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account is disabled, or the email address is unverified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "The template, version, or tag does not exist, or is not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Honour the `Retry-After` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v2/templates/{templateId}/tags/{tag}": {
      "put": {
        "operationId": "setTemplateTag",
        "summary": "Point a tag at a version",
        "tags": ["Versions & Tags"],
        "description": "Names a published version, so it can be identified by name rather than by number. Setting a tag the template already holds moves it to the version in the request. Sending the same version again succeeds unchanged.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["version"],
                "additionalProperties": false,
                "properties": {
                  "version": {
                    "type": "integer",
                    "minimum": 1
                  }
                }
              }
            }
          },
          "required": true
        },
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^(?!__.*__$)[A-Za-z0-9_-]+$"
            },
            "in": "path",
            "name": "templateId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "path",
            "name": "tag",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Tag set",
            "content": {
              "application/json": {
                "schema": {
                  "description": "Tag set",
                  "type": "object",
                  "properties": {
                    "tag": {
                      "type": "string"
                    },
                    "version": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request is malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unrecognised, revoked, or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account is disabled, or the email address is unverified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "The template, version, or tag does not exist, or is not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The request body exceeded 32 MB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "The `Content-Type` is not one Papermill accepts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Honour the `Retry-After` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "getTemplateTag",
        "summary": "Read one tag",
        "tags": ["Versions & Tags"],
        "description": "The version a tag names, and who last moved it there.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^(?!__.*__$)[A-Za-z0-9_-]+$"
            },
            "in": "path",
            "name": "templateId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "path",
            "name": "tag",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "The tag",
            "content": {
              "application/json": {
                "schema": {
                  "description": "The tag",
                  "type": "object",
                  "properties": {
                    "tag": {
                      "type": "string"
                    },
                    "version": {
                      "type": "integer"
                    },
                    "updated_at": {
                      "type": "string"
                    },
                    "updated_by": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "email": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request is malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unrecognised, revoked, or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account is disabled, or the email address is unverified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "The template, version, or tag does not exist, or is not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Honour the `Retry-After` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteTemplateTag",
        "summary": "Remove a tag",
        "tags": ["Versions & Tags"],
        "description": "Removes a tag, leaving the version it named untouched — versions are never deleted, so anything rendering by that version number keeps working. Anything rendering by the tag stops: `<template>@<tag>` names nothing once the tag is gone. `removed` is false when the template was not holding the tag.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^(?!__.*__$)[A-Za-z0-9_-]+$"
            },
            "in": "path",
            "name": "templateId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "path",
            "name": "tag",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Tag removed",
            "content": {
              "application/json": {
                "schema": {
                  "description": "Tag removed",
                  "type": "object",
                  "properties": {
                    "tag": {
                      "type": "string"
                    },
                    "removed": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request is malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unrecognised, revoked, or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account is disabled, or the email address is unverified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "The template, version, or tag does not exist, or is not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Honour the `Retry-After` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v2/templates/{templateId}/tags": {
      "get": {
        "operationId": "listTemplateTags",
        "summary": "List a template's tags",
        "tags": ["Versions & Tags"],
        "description": "Every tag the template holds and the version each one names, ordered by name. `has_more` is true when the template holds tags beyond the ones returned; send the last tag back as `start_after` to continue.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "query",
            "name": "start_after",
            "required": false
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^(?!__.*__$)[A-Za-z0-9_-]+$"
            },
            "in": "path",
            "name": "templateId",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Tags held",
            "content": {
              "application/json": {
                "schema": {
                  "description": "Tags held",
                  "type": "object",
                  "properties": {
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "tag": {
                            "type": "string"
                          },
                          "version": {
                            "type": "integer"
                          },
                          "updated_at": {
                            "type": "string"
                          },
                          "updated_by": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              },
                              "email": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request is malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unrecognised, revoked, or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account is disabled, or the email address is unverified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "The template, version, or tag does not exist, or is not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Honour the `Retry-After` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v2/templates/{templateId}/tags/{tag}/history": {
      "get": {
        "operationId": "listTemplateTagHistory",
        "summary": "List a tag's history",
        "tags": ["Versions & Tags"],
        "description": "Every recorded change to a tag, newest first: which version it was pointed at, which it named before, when, and by whom. A tag is a pointer that gets overwritten, so this is where earlier moves are kept. History survives removing the tag. The most recent changes are the ones returned, and `has_more` is true when the tag has been moved more times than fit — there is no way to page further back, so treat it as a depth limit rather than a cursor.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^(?!__.*__$)[A-Za-z0-9_-]+$"
            },
            "in": "path",
            "name": "templateId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "path",
            "name": "tag",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Recorded changes",
            "content": {
              "application/json": {
                "schema": {
                  "description": "Recorded changes",
                  "type": "object",
                  "properties": {
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "action": {
                            "type": "string"
                          },
                          "version": {
                            "type": "integer"
                          },
                          "previous_version": {
                            "type": "integer"
                          },
                          "at": {
                            "type": "string"
                          },
                          "by": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              },
                              "email": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request is malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unrecognised, revoked, or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account is disabled, or the email address is unverified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "The template, version, or tag does not exist, or is not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests. Honour the `Retry-After` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "servers": [
    {
      "url": "https://api.papermill.io",
      "description": "Production"
    }
  ],
  "security": [
    {
      "BearerAuth": []
    },
    {
      "ApiKeyHeader": []
    }
  ],
  "tags": [
    {
      "name": "Documents",
      "description": "Render and validate documents."
    },
    {
      "name": "Account",
      "description": "Verify credentials and read consumption."
    },
    {
      "name": "Versions & Tags",
      "description": "Publish a template's content as a version, and name versions with tags."
    },
    {
      "name": "Slugs",
      "description": "Give a template a readable name to use in place of its id."
    }
  ]
}
