{
  "openapi": "3.1.0",
  "info": {
    "title": "Paperkey API",
    "version": "1.0.0",
    "summary": "The licensing backend your AI agent wires up in 30 seconds",
    "description": "Software licensing API for local-first apps. License keys for desktop apps, CLI tools, IDE extensions, and plugins. REST API documented with OpenAPI 3.1. Your AI agent (Claude Code, Cursor, ChatGPT) handles the wiring. Open-source TypeScript SDK and MCP server included. A Keygen, Cryptlex, or Lemon Squeezy alternative, built indie-dev first.\n\nTwo authentication realms (never mix them):\n- **Public** (`pk_…`): for shipped client apps. Endpoints under `/v1/*`.\n- **Dashboard** (JWT or `sk_…`): for admin / server-side. All other endpoints.\n\nLicense key shape: 3 segments × 5 chars + 2-char checksum.\nDefault activations per license: 1.\n\nFull integration spec for LLMs: https://paperkey.dev/llms-full.txt",
    "contact": {
      "name": "Paperkey",
      "email": "hello@paperkey.dev",
      "url": "https://paperkey.dev"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://paperkey.dev/legal/terms"
    }
  },
  "servers": [
    {
      "url": "https://api.paperkey.dev",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "Full integration spec for coding agents",
    "url": "https://paperkey.dev/llms-full.txt"
  },
  "tags": [
    {
      "name": "Auth",
      "description": "Sign up, sign in, and inspect the current user."
    },
    {
      "name": "Products",
      "description": "A product is the app or service you license."
    },
    {
      "name": "Licenses",
      "description": "Per-customer credentials issued against a product."
    },
    {
      "name": "Public API",
      "description": "Authenticate with the public key (pk_…). These endpoints are what your shipped client app calls."
    },
    {
      "name": "Webhooks",
      "description": "Subscribe to events on a product. Each delivery POSTs JSON with an HMAC-SHA-256 signature."
    }
  ],
  "security": [
    {
      "bearerJwt": []
    },
    {
      "publicApiKey": []
    },
    {
      "secretApiKey": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerJwt": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Dashboard JWT issued by `POST /auth/login` or `POST /auth/register`."
      },
      "publicApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "Public API key, sent as `Authorization: Bearer pk_…`. Safe to ship in client apps."
      },
      "secretApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "Secret API key (`sk_…`), shown once on product creation. Server-side only."
      },
      "sessionCookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "paperkey_session",
        "description": "httpOnly session cookie set by the dashboard. 7-day TTL. Server-only."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error",
          "message"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Machine-readable error code.",
            "example": "unauthorized"
          },
          "message": {
            "type": "string",
            "description": "Human-readable explanation."
          },
          "details": {
            "type": "array",
            "description": "Optional structured details (e.g. zod validation issues).",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        }
      },
      "LicenseStatus": {
        "type": "string",
        "enum": [
          "active",
          "suspended",
          "expired",
          "revoked"
        ]
      },
      "LicenseSummary": {
        "type": "object",
        "required": [
          "id",
          "status",
          "activationsCount",
          "activationsLimit"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "clx1a2b3c4d5e6f7g8h9"
          },
          "status": {
            "$ref": "#/components/schemas/LicenseStatus"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "activationsCount": {
            "type": "integer",
            "minimum": 0
          },
          "activationsLimit": {
            "type": "integer",
            "minimum": 1
          },
          "isActivated": {
            "type": "boolean",
            "description": "True when the supplied fingerprint already holds a slot."
          },
          "metadata": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "type": "object",
                "additionalProperties": true
              }
            ],
            "description": "Free-form per-license metadata (tier, seats, etc.)."
          }
        }
      },
      "Activation": {
        "type": "object",
        "required": [
          "id",
          "fingerprint",
          "createdAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "fingerprint": {
            "type": "string",
            "example": "paperkey_fp_v1_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "example": "MacBook Pro"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ValidateRequest": {
        "type": "object",
        "required": [
          "license_key"
        ],
        "properties": {
          "license_key": {
            "type": "string",
            "example": "K7WX9-M3NP4-H8TRC-R2"
          },
          "fingerprint": {
            "type": "string",
            "description": "Optional but recommended. Lets `isActivated` reflect this machine.",
            "example": "paperkey_fp_v1_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
          }
        }
      },
      "ValidateResponse": {
        "oneOf": [
          {
            "type": "object",
            "required": [
              "valid",
              "license"
            ],
            "properties": {
              "valid": {
                "type": "boolean",
                "enum": [
                  true
                ]
              },
              "license": {
                "$ref": "#/components/schemas/LicenseSummary"
              }
            }
          },
          {
            "type": "object",
            "required": [
              "valid",
              "error",
              "message"
            ],
            "properties": {
              "valid": {
                "type": "boolean",
                "enum": [
                  false
                ]
              },
              "error": {
                "type": "string",
                "enum": [
                  "invalid_key",
                  "license_revoked",
                  "license_expired",
                  "license_suspended"
                ]
              },
              "message": {
                "type": "string"
              }
            }
          }
        ]
      },
      "ActivateRequest": {
        "type": "object",
        "required": [
          "license_key",
          "fingerprint"
        ],
        "properties": {
          "license_key": {
            "type": "string",
            "example": "K7WX9-M3NP4-H8TRC-R2"
          },
          "fingerprint": {
            "type": "string",
            "example": "paperkey_fp_v1_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
          },
          "name": {
            "type": "string",
            "description": "Optional human label (shows in dashboard).",
            "example": "MacBook Pro"
          }
        }
      },
      "ActivateResponse": {
        "type": "object",
        "required": [
          "success",
          "activationsRemaining"
        ],
        "properties": {
          "success": {
            "type": "boolean"
          },
          "activation": {
            "$ref": "#/components/schemas/Activation"
          },
          "activationsRemaining": {
            "type": "integer",
            "minimum": 0
          },
          "error": {
            "type": "string",
            "example": "activation_limit_reached"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "DeactivateRequest": {
        "type": "object",
        "required": [
          "license_key",
          "fingerprint"
        ],
        "properties": {
          "license_key": {
            "type": "string"
          },
          "fingerprint": {
            "type": "string"
          }
        }
      },
      "DeactivateResponse": {
        "type": "object",
        "required": [
          "success",
          "activationsRemaining"
        ],
        "properties": {
          "success": {
            "type": "boolean"
          },
          "activationsRemaining": {
            "type": "integer",
            "minimum": 0
          }
        }
      }
    },
    "responses": {
      "Error_validation_error": {
        "description": "400 validation_error: Body failed schema validation. `details` carries zod issues.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error_unauthorized": {
        "description": "401 unauthorized: Missing or invalid token / API key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error_forbidden": {
        "description": "403 forbidden: Authenticated but not allowed.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error_not_found": {
        "description": "404 not_found: Resource missing or owned by someone else (IDOR-safe).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error_activation_limit_reached": {
        "description": "403 activation_limit_reached: License is at maxActivations.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error_conflict": {
        "description": "409 conflict: Email already registered, key collision, etc.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error_body_too_large": {
        "description": "413 body_too_large: Request body exceeded 64 KB.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error_rate_limit_exceeded": {
        "description": "429 rate_limit_exceeded: Per-IP global limit hit.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error_auth_rate_limited": {
        "description": "429 auth_rate_limited: Too many `/auth/*` hits from one IP.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error_license_rate_limited": {
        "description": "429 license_rate_limited: Too many calls per license key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error_internal_error": {
        "description": "500 internal_error: Server bug. Safe to retry with exponential backoff.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "BadRequest": {
        "description": "Body failed schema validation.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid token / API key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource missing or owned by someone else.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit exceeded.",
        "headers": {
          "X-RateLimit-Limit": {
            "schema": {
              "type": "integer"
            }
          },
          "X-RateLimit-Remaining": {
            "schema": {
              "type": "integer"
            }
          },
          "X-RateLimit-Reset": {
            "schema": {
              "type": "integer"
            },
            "description": "Unix seconds."
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  },
  "paths": {
    "/auth/register": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Create a new dashboard account. Returns the user and a JWT.",
        "operationId": "post_auth_register",
        "security": [],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/auth/login": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Exchange credentials for a JWT.",
        "operationId": "post_auth_login",
        "security": [],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/auth/me": {
      "get": {
        "tags": [
          "Auth"
        ],
        "summary": "Return the current user; 200 with `{ user: null }` when signed out.",
        "operationId": "get_auth_me",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/auth/logout": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Clear the paperkey_session cookie.",
        "operationId": "post_auth_logout",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/products": {
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "List your products.",
        "operationId": "get_products",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Create a product.",
        "operationId": "post_products",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "description": "Response includes a secret key (sk_…) shown once only. Store it server-side.",
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/products/{id}": {
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "Get one product with its API keys.",
        "operationId": "get_products_id",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "tags": [
          "Products"
        ],
        "summary": "Update name, description, or keyPrefix.",
        "operationId": "patch_products_id",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "tags": [
          "Products"
        ],
        "summary": "Delete a product.",
        "operationId": "delete_products_id",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/products/{id}/api-keys": {
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Generate a new public/secret key pair (rotation).",
        "operationId": "post_products_id_api-keys",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/products/{id}/api-keys/{keyId}": {
      "delete": {
        "tags": [
          "Products"
        ],
        "summary": "Revoke a key pair. Apps using it stop working immediately.",
        "operationId": "delete_products_id_api-keys_keyId",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "keyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/products/{id}/licenses/export": {
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "Self-custody export. Every license + activation for this product. Always available, no support ticket. Audited.",
        "operationId": "get_products_id_licenses_export",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/licenses": {
      "get": {
        "tags": [
          "Licenses"
        ],
        "summary": "List licenses for a product.",
        "operationId": "get_licenses",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "tags": [
          "Licenses"
        ],
        "summary": "Issue a new license key (unique, includes a checksum).",
        "operationId": "post_licenses",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/licenses/{id}": {
      "get": {
        "tags": [
          "Licenses"
        ],
        "summary": "Get one license plus up to 100 most-recent activations.",
        "operationId": "get_licenses_id",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "tags": [
          "Licenses"
        ],
        "summary": "Update name, email, expiresAt, metadata.",
        "operationId": "patch_licenses_id",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/licenses/{id}/revoke": {
      "post": {
        "tags": [
          "Licenses"
        ],
        "summary": "Revoke (fires license.revoked).",
        "operationId": "post_licenses_id_revoke",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/licenses/{id}/reinstate": {
      "post": {
        "tags": [
          "Licenses"
        ],
        "summary": "Reinstate (fires license.reinstated).",
        "operationId": "post_licenses_id_reinstate",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/licenses/{id}/activations/{activationId}": {
      "delete": {
        "tags": [
          "Licenses"
        ],
        "summary": "Remove one activation slot (fires activation.removed).",
        "operationId": "delete_licenses_id_activations_activationId",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "activationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/licenses/validate": {
      "post": {
        "tags": [
          "Public API"
        ],
        "summary": "Check whether a license key is currently usable.",
        "operationId": "post_v1_licenses_validate",
        "security": [
          {
            "publicApiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ValidateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/licenses/activate": {
      "post": {
        "tags": [
          "Public API"
        ],
        "summary": "Bind a fingerprint to a license. Idempotent on the same fingerprint.",
        "operationId": "post_v1_licenses_activate",
        "security": [
          {
            "publicApiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActivateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActivateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/licenses/deactivate": {
      "post": {
        "tags": [
          "Public API"
        ],
        "summary": "Release a fingerprint slot.",
        "operationId": "post_v1_licenses_deactivate",
        "security": [
          {
            "publicApiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeactivateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeactivateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/products/{id}/webhooks": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhooks on a product.",
        "operationId": "get_products_id_webhooks",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Create a webhook (URL must be HTTPS).",
        "operationId": "post_products_id_webhooks",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "description": "Returns the webhook plus the secret (shown once).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/products/{id}/webhooks/{webhookId}": {
      "patch": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Pause/resume or change url/events. Resuming clears the failure counter.",
        "operationId": "patch_products_id_webhooks_webhookId",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhookId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Delete a webhook.",
        "operationId": "delete_products_id_webhooks_webhookId",
        "security": [
          {
            "bearerJwt": []
          },
          {
            "sessionCookie": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhookId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  }
}