{
  "openapi": "3.1.0",
  "info": {
    "title": "Intero Dreams API",
    "version": "1.0.0",
    "summary": "Dream interpretation API and Markdown content access for interodreams.com.",
    "description": "Public HTTP interface of Intero Dreams: an AI dream interpreter, a follow-up chat, journal endpoints for signed-in users, and newsletter sign-up. Every content page (symbols, categories, themes, and the informational pages) is also available as Markdown at its normal URL by sending `Accept: text/markdown` or appending `.md`, following the acceptmarkdown.com convention. Content is for self-reflection and educational use only, not medical advice.\n\n## Versioning\n\n- The current version is v1, reached at /api/v1/. Every response carries an API-Version header naming the version that served it.\n- Breaking changes ship as a new version prefix (/api/v1/ becomes /api/v2/). Within a version, we only add: new endpoints, new optional request fields, and new response fields. Treat unknown response fields as forgiving — do not fail on them.\n- A version scheduled for removal answers with Deprecation: true, a Sunset header carrying the removal date, and a Link header pointing at its successor. Sunset is set at least 180 days ahead of the date it names.\n- The unversioned /api/... paths are aliases of /api/v1/... They answer identically, and they carry Deprecation: true plus a Link to the versioned path. They have no Sunset date and will not be removed without one.\n\n## Rate limits\n\n- `ai`: 10 requests per 86400 seconds.\n- `write`: 60 requests per 3600 seconds.\n- `read`: 240 requests per 3600 seconds.\n\nEvery response carries RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset and RateLimit-Policy. A 429 additionally carries Retry-After in seconds. Read them as you go rather than waiting to be refused.\n\n## Errors\n\nEvery 4xx and 5xx returns JSON with a stable `code`, a `message`, a `hint` saying what to do next, and a `requestId`. Branch on `code`, never on `message`. Codes: `invalid_request`, `unauthenticated`, `forbidden`, `not_found`, `method_not_allowed`, `unsupported_media_type`, `trial_exhausted`, `not_a_dream`, `rate_limited`, `upstream_unavailable`, `internal_error`.",
    "termsOfService": "https://interodreams.com/terms",
    "contact": {
      "name": "Intero Dreams support",
      "email": "hello@interodreams.com",
      "url": "https://interodreams.com/contact"
    }
  },
  "externalDocs": {
    "description": "Intero Dreams developer documentation",
    "url": "https://interodreams.com/developers"
  },
  "x-api-version": "v1",
  "x-api-base-path": "/api/v1",
  "x-versioning-policy": [
    "The current version is v1, reached at /api/v1/. Every response carries an API-Version header naming the version that served it.",
    "Breaking changes ship as a new version prefix (/api/v1/ becomes /api/v2/). Within a version, we only add: new endpoints, new optional request fields, and new response fields. Treat unknown response fields as forgiving — do not fail on them.",
    "A version scheduled for removal answers with Deprecation: true, a Sunset header carrying the removal date, and a Link header pointing at its successor. Sunset is set at least 180 days ahead of the date it names.",
    "The unversioned /api/... paths are aliases of /api/v1/... They answer identically, and they carry Deprecation: true plus a Link to the versioned path. They have no Sunset date and will not be removed without one."
  ],
  "x-sunset-notice-days": 180,
  "x-rate-limits": [
    {
      "policy": "ai",
      "limit": 10,
      "windowSeconds": 86400
    },
    {
      "policy": "write",
      "limit": 60,
      "windowSeconds": 3600
    },
    {
      "policy": "read",
      "limit": 240,
      "windowSeconds": 3600
    }
  ],
  "x-error-codes": [
    {
      "code": "invalid_request",
      "status": 400,
      "hint": "Check the request against the schema in /openapi.json and retry with corrected fields."
    },
    {
      "code": "unauthenticated",
      "status": 401,
      "hint": "Sign in at /login to obtain a session cookie, then retry with that cookie attached."
    },
    {
      "code": "forbidden",
      "status": 403,
      "hint": "Confirm the resource belongs to the authenticated user. Do not retry without changing the request."
    },
    {
      "code": "not_found",
      "status": 404,
      "hint": "See /openapi.json for the endpoints that exist. Do not retry this path."
    },
    {
      "code": "method_not_allowed",
      "status": 405,
      "hint": "Read the Allow header on this response for the methods this path accepts."
    },
    {
      "code": "unsupported_media_type",
      "status": 415,
      "hint": "Send Content-Type: application/json with a JSON-encoded body."
    },
    {
      "code": "trial_exhausted",
      "status": 401,
      "hint": "Create an account at /signup and retry with a session cookie. Retrying anonymously will fail again."
    },
    {
      "code": "not_a_dream",
      "status": 422,
      "hint": "Send a narrative description — where you were, who was there, how it felt — rather than keywords. Retrying the same text will fail again."
    },
    {
      "code": "rate_limited",
      "status": 429,
      "hint": "Wait for the number of seconds in Retry-After, then retry. Read RateLimit-Remaining on every response to pace yourself before you get here."
    },
    {
      "code": "upstream_unavailable",
      "status": 503,
      "hint": "Retry with exponential backoff. If it persists for more than a few minutes the fault is ours, not the request's."
    },
    {
      "code": "internal_error",
      "status": 500,
      "hint": "The request was probably fine. Retry once with backoff; if it keeps failing, quote requestId when you contact support."
    }
  ],
  "servers": [
    {
      "url": "https://interodreams.com",
      "description": "Site root. API paths are absolute and versioned under /api/v1/; current version v1."
    }
  ],
  "tags": [
    {
      "name": "Interpretation",
      "description": "AI dream interpretation and follow-up chat."
    },
    {
      "name": "Journal",
      "description": "Signed-in dream journal (first-party UI)."
    },
    {
      "name": "Content",
      "description": "Symbol, category and theme pages as HTML or Markdown."
    },
    {
      "name": "Newsletter"
    }
  ],
  "paths": {
    "/api/v1/interpretDream": {
      "post": {
        "tags": [
          "Interpretation"
        ],
        "operationId": "interpretDream",
        "summary": "Interpret a dream narrative",
        "description": "Returns a structured interpretation. Anonymous callers receive one interpretation per UTC day, tracked in an HttpOnly cookie (`id_trial`) set on the response; signed-in Supabase sessions receive ten per rolling 24 hours. Input that is not a dream returns 422 rather than an invented reading.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InterpretDreamRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Interpretation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DreamInterpretation"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (e.g. dreamText shorter than 10 characters).",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Anonymous free trial exhausted; create an account to continue.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Error"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "authRequired": {
                          "type": "boolean",
                          "const": true
                        },
                        "trialExhausted": {
                          "type": "boolean",
                          "const": true
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "405": {
            "description": "Method not supported on this path. The Allow header lists the ones that are.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The text does not describe a dream.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Error"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "notADream": {
                          "type": "boolean",
                          "const": true
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Signed-in daily limit of 10 interpretations reached.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying. Sent on 429 only."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Interpretation failed.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/chat": {
      "post": {
        "tags": [
          "Interpretation"
        ],
        "operationId": "chatAboutDream",
        "summary": "Continue a conversation about a dream",
        "description": "Requires a signed-in Supabase session cookie. Limited to 10 messages per rolling 24 hours.",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChatRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Assistant reply",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "reply"
                  ],
                  "properties": {
                    "reply": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation failed.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported on this path. The Allow header lists the ones that are.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Daily chat limit reached; the message includes the reset countdown.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying. Sent on 429 only."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Chat failed.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/saveDream": {
      "post": {
        "tags": [
          "Journal"
        ],
        "operationId": "saveDream",
        "summary": "Save an interpretation to the caller's journal",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SaveDreamRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "dreamId"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "dreamId": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation failed.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported on this path. The Allow header lists the ones that are.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Retry-After carries the number of seconds to wait.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying. Sent on 429 only."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure while handling the request.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/getUserDreams": {
      "get": {
        "tags": [
          "Journal"
        ],
        "operationId": "getUserDreams",
        "summary": "List the caller's recent dreams and journal stats",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Up to 20 most recent dreams plus aggregate stats.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Not signed in.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported on this path. The Allow header lists the ones that are.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Retry-After carries the number of seconds to wait.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying. Sent on 429 only."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure while handling the request.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/deleteDream": {
      "post": {
        "tags": [
          "Journal"
        ],
        "operationId": "deleteDream",
        "summary": "Soft-delete one of the caller's dreams",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "dreamId"
                ],
                "properties": {
                  "dreamId": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid dream ID.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported on this path. The Allow header lists the ones that are.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Retry-After carries the number of seconds to wait.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying. Sent on 429 only."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure while handling the request.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/newsletter": {
      "post": {
        "tags": [
          "Newsletter"
        ],
        "operationId": "subscribeNewsletter",
        "summary": "Subscribe an email address to the newsletter",
        "description": "Re-submitting an existing address is a no-op success. Only call on behalf of a person who explicitly asked to subscribe.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 254
                  },
                  "source": {
                    "type": "string",
                    "maxLength": 120
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Subscribed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid email, or a body that is not JSON.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported on this path. The Allow header lists the ones that are.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Retry-After carries the number of seconds to wait.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying. Sent on 429 only."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure while handling the request.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "The subscriber store rejected the write. Retry with backoff.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/interpretDream": {
      "post": {
        "tags": [
          "Interpretation"
        ],
        "operationId": "interpretDreamDeprecated",
        "summary": "Interpret a dream narrative",
        "description": "Unversioned alias of `/api/v1/interpretDream`. Identical behaviour; responds with Deprecation: true and a Link to the versioned path. Use `/api/v1/interpretDream` instead. Returns a structured interpretation. Anonymous callers receive one interpretation per UTC day, tracked in an HttpOnly cookie (`id_trial`) set on the response; signed-in Supabase sessions receive ten per rolling 24 hours. Input that is not a dream returns 422 rather than an invented reading.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InterpretDreamRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Interpretation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DreamInterpretation"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (e.g. dreamText shorter than 10 characters).",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Anonymous free trial exhausted; create an account to continue.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Error"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "authRequired": {
                          "type": "boolean",
                          "const": true
                        },
                        "trialExhausted": {
                          "type": "boolean",
                          "const": true
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "405": {
            "description": "Method not supported on this path. The Allow header lists the ones that are.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The text does not describe a dream.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Error"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "notADream": {
                          "type": "boolean",
                          "const": true
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Signed-in daily limit of 10 interpretations reached.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying. Sent on 429 only."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Interpretation failed.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "deprecated": true
      }
    },
    "/api/chat": {
      "post": {
        "tags": [
          "Interpretation"
        ],
        "operationId": "chatAboutDreamDeprecated",
        "summary": "Continue a conversation about a dream",
        "description": "Unversioned alias of `/api/v1/chat`. Identical behaviour; responds with Deprecation: true and a Link to the versioned path. Use `/api/v1/chat` instead. Requires a signed-in Supabase session cookie. Limited to 10 messages per rolling 24 hours.",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChatRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Assistant reply",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "reply"
                  ],
                  "properties": {
                    "reply": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation failed.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported on this path. The Allow header lists the ones that are.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Daily chat limit reached; the message includes the reset countdown.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying. Sent on 429 only."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Chat failed.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "deprecated": true
      }
    },
    "/api/saveDream": {
      "post": {
        "tags": [
          "Journal"
        ],
        "operationId": "saveDreamDeprecated",
        "summary": "Save an interpretation to the caller's journal",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SaveDreamRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "dreamId"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "dreamId": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation failed.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported on this path. The Allow header lists the ones that are.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Retry-After carries the number of seconds to wait.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying. Sent on 429 only."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure while handling the request.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "deprecated": true,
        "description": "Unversioned alias of `/api/v1/saveDream`. Identical behaviour; responds with Deprecation: true and a Link to the versioned path. Use `/api/v1/saveDream` instead. "
      }
    },
    "/api/getUserDreams": {
      "get": {
        "tags": [
          "Journal"
        ],
        "operationId": "getUserDreamsDeprecated",
        "summary": "List the caller's recent dreams and journal stats",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Up to 20 most recent dreams plus aggregate stats.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Not signed in.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported on this path. The Allow header lists the ones that are.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Retry-After carries the number of seconds to wait.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying. Sent on 429 only."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure while handling the request.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "deprecated": true,
        "description": "Unversioned alias of `/api/v1/getUserDreams`. Identical behaviour; responds with Deprecation: true and a Link to the versioned path. Use `/api/v1/getUserDreams` instead. "
      }
    },
    "/api/deleteDream": {
      "post": {
        "tags": [
          "Journal"
        ],
        "operationId": "deleteDreamDeprecated",
        "summary": "Soft-delete one of the caller's dreams",
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "dreamId"
                ],
                "properties": {
                  "dreamId": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid dream ID.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported on this path. The Allow header lists the ones that are.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Retry-After carries the number of seconds to wait.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying. Sent on 429 only."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure while handling the request.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "deprecated": true,
        "description": "Unversioned alias of `/api/v1/deleteDream`. Identical behaviour; responds with Deprecation: true and a Link to the versioned path. Use `/api/v1/deleteDream` instead. "
      }
    },
    "/api/newsletter": {
      "post": {
        "tags": [
          "Newsletter"
        ],
        "operationId": "subscribeNewsletterDeprecated",
        "summary": "Subscribe an email address to the newsletter",
        "description": "Unversioned alias of `/api/v1/newsletter`. Identical behaviour; responds with Deprecation: true and a Link to the versioned path. Use `/api/v1/newsletter` instead. Re-submitting an existing address is a no-op success. Only call on behalf of a person who explicitly asked to subscribe.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 254
                  },
                  "source": {
                    "type": "string",
                    "maxLength": 120
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Subscribed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid email, or a body that is not JSON.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Method not supported on this path. The Allow header lists the ones that are.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Retry-After carries the number of seconds to wait.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying. Sent on 429 only."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure while handling the request.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "The subscriber store rejected the write. Retry with backoff.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "deprecated": true
      }
    },
    "/symbols/{slug}": {
      "get": {
        "tags": [
          "Content"
        ],
        "operationId": "getSymbolPage",
        "summary": "Dream symbol page as HTML or Markdown",
        "description": "Content negotiation on the Accept header (acceptmarkdown.com). `Accept: text/markdown` returns the interpretation as Markdown; browsers get HTML. Responses carry `Vary: Accept`. Appending `.md` to the path also returns Markdown. The same applies to `/`, `/symbols`, `/symbols/all`, `/categories`, `/categories/{slug}`, `/themes`, `/themes/{slug}`, `/about`, `/methodology`, `/contact`, `/developers`, `/privacy` and `/terms`.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Kebab-case symbol slug ending in -dream-meaning, e.g. snake-dream-meaning. The full list is in /sitemap-dream-meanings.xml or /symbols/all.md.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
            }
          },
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "examples": [
                "text/markdown",
                "text/html"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Symbol interpretation",
            "headers": {
              "Vary": {
                "schema": {
                  "type": "string"
                },
                "description": "Always includes Accept."
              }
            },
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "No published symbol with that slug."
          },
          "405": {
            "description": "Method not supported on this path. The Allow header lists the ones that are.",
            "headers": {
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests permitted in the current window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requests still permitted in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the window resets."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "Window description, for example \"60;w=3600\"."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "406": {
            "description": "Accept header rules out both text/html and text/markdown.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "sessionCookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "sb-access-token",
        "description": "Supabase auth session established by signing in at /auth/sign-in. Cookie names are prefixed with the project ref."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error",
          "code",
          "message",
          "hint",
          "docs",
          "status",
          "requestId"
        ],
        "description": "Every 4xx and 5xx uses this shape. Branch on `code`, which is stable; `message` is prose and may be reworded at any time.",
        "properties": {
          "error": {
            "type": "string",
            "description": "Same text as `message`. Present so older clients that read a single string keep working."
          },
          "code": {
            "type": "string",
            "enum": [
              "invalid_request",
              "unauthenticated",
              "forbidden",
              "not_found",
              "method_not_allowed",
              "unsupported_media_type",
              "trial_exhausted",
              "not_a_dream",
              "rate_limited",
              "upstream_unavailable",
              "internal_error"
            ],
            "description": "Stable machine-readable identifier for the failure."
          },
          "message": {
            "type": "string",
            "description": "What went wrong, in a sentence."
          },
          "hint": {
            "type": "string",
            "description": "What to do next. Says explicitly whether retrying the same request can succeed."
          },
          "docs": {
            "type": "string",
            "format": "uri"
          },
          "status": {
            "type": "integer"
          },
          "requestId": {
            "type": "string",
            "description": "Quote this when reporting a failure."
          }
        }
      },
      "InterpretDreamRequest": {
        "type": "object",
        "required": [
          "dreamText"
        ],
        "properties": {
          "dreamText": {
            "type": "string",
            "minLength": 10,
            "maxLength": 2000,
            "description": "The dream, in the dreamer's own words."
          },
          "mood": {
            "type": "string",
            "default": "Neutral",
            "description": "How the dreamer felt, free text."
          },
          "isRecurring": {
            "type": "boolean",
            "default": false
          },
          "isLucid": {
            "type": "boolean",
            "default": false
          },
          "perspective": {
            "type": "string",
            "enum": [
              "Modern",
              "Freudian",
              "Jungian",
              "Universal"
            ],
            "default": "Modern"
          }
        }
      },
      "DreamInterpretation": {
        "type": "object",
        "properties": {
          "is_dream": {
            "type": "boolean"
          },
          "title": {
            "type": "string"
          },
          "summary": {
            "type": "string",
            "description": "Two-paragraph interpretation through the chosen lens."
          },
          "core_meaning": {
            "type": "string"
          },
          "emotional_insight": {
            "type": "string"
          },
          "key_symbols": {
            "type": "array",
            "maxItems": 3,
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "meaning": {
                  "type": "string"
                }
              }
            }
          },
          "reflection_questions": {
            "type": "array",
            "maxItems": 3,
            "items": {
              "type": "string"
            }
          },
          "sentiment": {
            "type": "string",
            "enum": [
              "Positive",
              "Neutral",
              "Mixed",
              "Negative",
              "Distressing"
            ]
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "lucidity_suggestion": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "isTrial": {
            "type": "boolean",
            "description": "True when this used the anonymous free reading."
          },
          "trialRemaining": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Free readings left today for anonymous callers; null when signed in."
          }
        }
      },
      "ChatRequest": {
        "type": "object",
        "required": [
          "history",
          "dreamContext"
        ],
        "properties": {
          "history": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "role",
                "content"
              ],
              "properties": {
                "role": {
                  "type": "string",
                  "enum": [
                    "user",
                    "assistant"
                  ]
                },
                "content": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 2000
                }
              }
            }
          },
          "dreamContext": {
            "type": "string",
            "minLength": 1
          }
        }
      },
      "SaveDreamRequest": {
        "type": "object",
        "required": [
          "dreamText",
          "analysis"
        ],
        "properties": {
          "dreamText": {
            "type": "string",
            "minLength": 10,
            "maxLength": 2000
          },
          "analysis": {
            "$ref": "#/components/schemas/DreamInterpretation"
          },
          "mood": {
            "type": "string",
            "default": "Neutral"
          },
          "isLucid": {
            "type": "boolean",
            "default": false
          },
          "isRecurring": {
            "type": "boolean",
            "default": false
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "chatHistory": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "role": {
                  "type": "string",
                  "enum": [
                    "user",
                    "assistant"
                  ]
                },
                "content": {
                  "type": "string",
                  "maxLength": 2000
                }
              }
            }
          }
        }
      }
    }
  }
}