{
  "openapi": "3.1.0",
  "info": {
    "title": "ZensInk API",
    "version": "1.0.0",
    "description": "Store and licensing API for zens.ink — checkout, purchase status, license verification, and Pro package download. All errors are structured JSON: `{\"error\": \"message\", \"hint\": \"...\"}` with a matching HTTP status code. Agent-facing docs: https://zens.ink/developers/ — llms.txt: https://zens.ink/llms.txt",
    "contact": {
      "name": "ZensInk Support",
      "email": "support@zens.ink",
      "url": "https://zens.ink/contact/"
    }
  },
  "servers": [
    {
      "url": "https://zens.ink",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Store",
      "description": "Checkout and purchase status"
    },
    {
      "name": "Licensing",
      "description": "License verification and package download"
    },
    {
      "name": "Webhooks",
      "description": "Inbound payment webhooks (internal, signature-verified)"
    }
  ],
  "paths": {
    "/api/checkout": {
      "post": {
        "operationId": "createCheckout",
        "tags": [
          "Store"
        ],
        "summary": "Create a Creem checkout session",
        "description": "Creates a hosted checkout session for a ZensInk product and returns the checkout URL. Product IDs are embedded on the pricing page (https://zens.ink/pricing/).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "product_id"
                ],
                "properties": {
                  "product_id": {
                    "type": "string",
                    "description": "Creem product ID (Pro 1-Year, Pro Lifetime, or Supporter plan).",
                    "examples": [
                      "prod_qu2dGPTHYqFG7nLCUnRVO"
                    ]
                  },
                  "discount_code": {
                    "type": "string",
                    "description": "Optional discount code applied at checkout.",
                    "examples": [
                      "LAUNCH40"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Checkout session created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "checkout_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Hosted checkout URL to redirect the buyer to."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/purchase-status": {
      "get": {
        "operationId": "getPurchaseStatus",
        "tags": [
          "Store"
        ],
        "summary": "Poll checkout status and receive the license key on payment",
        "description": "Looks up the checkout session created by createCheckout (same `rid`), queries the payment provider in real time, and returns `pending` until payment completes. On completion, returns the license key directly.",
        "parameters": [
          {
            "name": "rid",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Request ID echoed in the checkout success URL (zens.ink/unlock?rid=...)."
          }
        ],
        "responses": {
          "200": {
            "description": "Current purchase state.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "paid",
                        "error"
                      ],
                      "description": "pending = not paid yet; paid = license delivered."
                    },
                    "licenseKey": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "License key. Present when status=paid."
                    },
                    "plan": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Plan tier (annual | lifetime | supporter). Present when known."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/verify-key": {
      "post": {
        "operationId": "verifyLicenseKey",
        "tags": [
          "Licensing"
        ],
        "summary": "Validate a license key and mint a download token",
        "description": "Validates a ZensInk license key (local registry first, payment provider fallback). On success, returns a short-lived (10 minute) signed token URL for downloading the Pro package.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "key"
                ],
                "properties": {
                  "key": {
                    "type": "string",
                    "minLength": 8,
                    "description": "License key from the purchase receipt or unlock page."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verification result (invalid keys also return 200 with valid=false).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "valid"
                  ],
                  "properties": {
                    "valid": {
                      "type": "boolean"
                    },
                    "download_url": {
                      "type": "string",
                      "description": "Signed download URL (/api/download?t=...). Present when valid=true."
                    },
                    "error": {
                      "type": "string",
                      "description": "Human-readable reason. Present when valid=false."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    },
    "/api/download": {
      "get": {
        "operationId": "downloadProPackage",
        "tags": [
          "Licensing"
        ],
        "summary": "Download the watermarked Pro package ZIP",
        "description": "Streams the Pro package ZIP, watermarked per buyer. Requires the signed token from verifyLicenseKey; tokens expire after 10 minutes (HTTP 410 after that).",
        "parameters": [
          {
            "name": "t",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Signed download token returned by verifyLicenseKey (format: expires.keyHash.signature)."
          }
        ],
        "responses": {
          "200": {
            "description": "ZIP archive (application/zip) with per-buyer license watermark.",
            "content": {
              "application/zip": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "410": {
            "description": "Download link expired — re-verify the license key to get a fresh token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Download link expired. Please verify your key again."
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/webhook": {
      "post": {
        "operationId": "creemWebhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Creem payment webhook (internal)",
        "description": "Inbound webhook from the payment provider, verified with an HMAC-SHA256 signature header. Not intended for agent or third-party calls; documented for completeness.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Creem event payload (checkout.completed)."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Event processed (or ignored)."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message."
          },
          "status": {
            "type": "integer",
            "description": "HTTP status code, echoed when useful."
          },
          "hint": {
            "type": "string",
            "description": "Resolution hint — where to look next."
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Malformed request (missing or invalid parameters).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Invalid download token signature.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource not found.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ServerError": {
        "description": "Server-side configuration or upstream error.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "BadGateway": {
        "description": "Upstream payment provider error.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unavailable": {
        "description": "Service temporarily unavailable (e.g. payments not configured).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}