{
  "openapi": "3.1.0",
  "info": {
    "title": "Shipstar API",
    "description": "Public Shipstar REST API (v1). Authenticate with an API token from the dashboard: Authorization: Bearer <token>. For agent access prefer the MCP server at https://mcp.shipstar.ai/mcp (OAuth 2.1, streamable HTTP). Responses carry standard RateLimit-* headers (and Retry-After on 429) so clients can self-throttle. Versioning & deprecation policy: https://docs.shipstar.ai/api-reference/versioning",
    "version": "1.0.0"
  },
  "paths": {
    "/health": {
      "get": {
        "summary": "Health Check",
        "description": "Health check endpoint for V1 API.\nThis endpoint does not require authentication.",
        "operationId": "health_check_health_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "security": []
      }
    },
    "/changelogs": {
      "get": {
        "tags": [
          "changelog"
        ],
        "summary": "List Published Changelogs",
        "description": "List all published changelogs, newest first.\nThis endpoint does not require authentication.",
        "operationId": "list_published_changelogs_changelogs_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded — wait Retry-After seconds before retrying",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  },
                  "example": {
                    "detail": "Rate limit exceeded. Please try again later."
                  }
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/changelog/{public_slug}": {
      "get": {
        "tags": [
          "changelog"
        ],
        "summary": "Get Public Changelog",
        "description": "Get a published changelog by its public slug.\nThis endpoint does not require authentication.",
        "operationId": "get_public_changelog_changelog__public_slug__get",
        "parameters": [
          {
            "name": "public_slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Public Slug"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded — wait Retry-After seconds before retrying",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  },
                  "example": {
                    "detail": "Rate limit exceeded. Please try again later."
                  }
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/changelog/{public_slug}/feed": {
      "get": {
        "tags": [
          "changelog"
        ],
        "summary": "Get Public Changelog Feed",
        "description": "Get a published changelog as an RSS 2.0 feed.\nThis endpoint does not require authentication.",
        "operationId": "get_public_changelog_feed_changelog__public_slug__feed_get",
        "parameters": [
          {
            "name": "public_slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Public Slug"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded — wait Retry-After seconds before retrying",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  },
                  "example": {
                    "detail": "Rate limit exceeded. Please try again later."
                  }
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/blogs": {
      "get": {
        "tags": [
          "blog"
        ],
        "summary": "List Published Blog Posts",
        "description": "List all published blog posts, newest first.\nReturns an array of blog post objects with title, content, and metadata.\nThis endpoint does not require authentication.",
        "operationId": "list_published_blog_posts_blogs_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded — wait Retry-After seconds before retrying",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  },
                  "example": {
                    "detail": "Rate limit exceeded. Please try again later."
                  }
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/blog/{public_slug}": {
      "get": {
        "tags": [
          "blog"
        ],
        "summary": "Get Public Blog Post",
        "description": "Get a published blog post by its public slug.\nReturns the blog post markdown content and metadata.\nThis endpoint does not require authentication.",
        "operationId": "get_public_blog_post_blog__public_slug__get",
        "parameters": [
          {
            "name": "public_slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Public Slug"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded — wait Retry-After seconds before retrying",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  },
                  "example": {
                    "detail": "Rate limit exceeded. Please try again later."
                  }
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/blog/{public_slug}/feed": {
      "get": {
        "tags": [
          "blog"
        ],
        "summary": "Get Public Blog Feed",
        "description": "Get a published blog post as an RSS 2.0 feed item.\nThis endpoint does not require authentication.",
        "operationId": "get_public_blog_feed_blog__public_slug__feed_get",
        "parameters": [
          {
            "name": "public_slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Public Slug"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded — wait Retry-After seconds before retrying",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  },
                  "example": {
                    "detail": "Rate limit exceeded. Please try again later."
                  }
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/blogs/feed": {
      "get": {
        "tags": [
          "blog"
        ],
        "summary": "Get All Blogs Feed",
        "description": "Get an RSS 2.0 feed of all published blog posts.\nThis endpoint does not require authentication.",
        "operationId": "get_all_blogs_feed_blogs_feed_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded — wait Retry-After seconds before retrying",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  },
                  "example": {
                    "detail": "Rate limit exceeded. Please try again later."
                  }
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/kb": {
      "get": {
        "tags": [
          "kb"
        ],
        "summary": "List Published Kb Articles",
        "description": "List all published knowledge base article sets, newest first.\nThis endpoint does not require authentication.",
        "operationId": "list_published_kb_articles_kb_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded — wait Retry-After seconds before retrying",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  },
                  "example": {
                    "detail": "Rate limit exceeded. Please try again later."
                  }
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/kb/{public_slug}": {
      "get": {
        "tags": [
          "kb"
        ],
        "summary": "Get Public Kb Articles",
        "description": "Get published knowledge base articles by public slug.\nReturns the articles array and metadata.\nThis endpoint does not require authentication.",
        "operationId": "get_public_kb_articles_kb__public_slug__get",
        "parameters": [
          {
            "name": "public_slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Public Slug"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded — wait Retry-After seconds before retrying",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  },
                  "example": {
                    "detail": "Rate limit exceeded. Please try again later."
                  }
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/changelog/subscribe": {
      "post": {
        "tags": [
          "changelog-subscriptions"
        ],
        "summary": "Subscribe To Changelog",
        "description": "Subscribe an email address to a project's changelog updates.\nSends a confirmation email (double opt-in). No authentication required.\nAlways returns 200 to prevent email enumeration.",
        "operationId": "subscribe_to_changelog_changelog_subscribe_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChangelogSubscribeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChangelogSubscribeResponse"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded — wait Retry-After seconds before retrying",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  },
                  "example": {
                    "detail": "Rate limit exceeded. Please try again later."
                  }
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/changelog/confirm/{token}": {
      "get": {
        "tags": [
          "changelog-subscriptions"
        ],
        "summary": "Confirm Changelog Subscription",
        "description": "Confirm a changelog subscription via the token sent in the confirmation email.\nNo authentication required.",
        "operationId": "confirm_changelog_subscription_changelog_confirm__token__get",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Token"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded — wait Retry-After seconds before retrying",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  },
                  "example": {
                    "detail": "Rate limit exceeded. Please try again later."
                  }
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/changelog/unsubscribe/{token}": {
      "get": {
        "tags": [
          "changelog-subscriptions"
        ],
        "summary": "Unsubscribe From Changelog",
        "description": "Unsubscribe from changelog updates. Hard-deletes the subscription.\nNo authentication required.",
        "operationId": "unsubscribe_from_changelog_changelog_unsubscribe__token__get",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Token"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChangelogUnsubscribeResponse"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded — wait Retry-After seconds before retrying",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  },
                  "example": {
                    "detail": "Rate limit exceeded. Please try again later."
                  }
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/email/unsubscribe/{token}": {
      "get": {
        "tags": [
          "mailing-lists"
        ],
        "summary": "Unsubscribe From Mailing List",
        "description": "Unsubscribe from a mailing list via the link in a release notes email.\n\nNo authentication required.",
        "operationId": "unsubscribe_from_mailing_list_email_unsubscribe__token__get",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Token"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded — wait Retry-After seconds before retrying",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  },
                  "example": {
                    "detail": "Rate limit exceeded. Please try again later."
                  }
                }
              }
            }
          }
        },
        "security": []
      },
      "post": {
        "tags": [
          "mailing-lists"
        ],
        "summary": "Unsubscribe From Mailing List One Click",
        "description": "RFC 8058 one-click unsubscribe target (List-Unsubscribe-Post header).\n\nMail clients POST here without a body. No authentication required.",
        "operationId": "unsubscribe_from_mailing_list_one_click_email_unsubscribe__token__post",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Token"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded — wait Retry-After seconds before retrying",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  },
                  "example": {
                    "detail": "Rate limit exceeded. Please try again later."
                  }
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/email/lists": {
      "get": {
        "tags": [
          "mailing-lists"
        ],
        "summary": "List the project's mailing lists",
        "description": "Lists the mailing lists of the project the API token belongs to, with\n    recipient counts. Use the returned `id` values with\n    `POST /email/lists/{list_id}/recipients`.\n\n    ## Authentication\n    Requires an API token (created in the dashboard). Pass it as a Bearer\n    token in the Authorization header:\n    ```\n    Authorization: Bearer YOUR_API_TOKEN\n    ```",
        "operationId": "list_mailing_lists_email_lists_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/MailingListRead"
                  },
                  "type": "array",
                  "title": "Response List Mailing Lists Email Lists Get"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded — wait Retry-After seconds before retrying",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  },
                  "example": {
                    "detail": "Rate limit exceeded. Please try again later."
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ]
      }
    },
    "/email/lists/{list_id}/recipients": {
      "post": {
        "tags": [
          "mailing-lists"
        ],
        "summary": "Add recipients to a mailing list",
        "description": "Bulk-adds email addresses to a mailing list, e.g. syncing signups from\n    your own database. Send up to 1000 addresses per request:\n    ```\n    {\"emails\": [\"one@example.com\", \"two@example.com\"]}\n    ```\n\n    Each address is validated individually; invalid entries are returned in\n    `invalid` rather than failing the batch. Addresses already on the list —\n    including unsubscribed ones — are counted in `skipped_existing`, so\n    re-syncing never resurrects an opt-out. A list holds at most 500 active\n    recipients.\n\n    ## Authentication\n    Requires an API token (created in the dashboard). Pass it as a Bearer\n    token in the Authorization header:\n    ```\n    Authorization: Bearer YOUR_API_TOKEN\n    ```\n    The list must belong to the token's project. List ids come from\n    `GET /email/lists`.",
        "operationId": "add_mailing_list_recipients_email_lists__list_id__recipients_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "list_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "List Id"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RecipientBulkAdd"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecipientBulkAddResponse"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded — wait Retry-After seconds before retrying",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  },
                  "example": {
                    "detail": "Rate limit exceeded. Please try again later."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/me": {
      "get": {
        "tags": [
          "authentication"
        ],
        "summary": "Get current user via API token",
        "description": "Retrieves the profile of the user authenticated via API token.\n\n    ## Authentication\n    This endpoint requires an API token (created in the API Playground).\n    Pass the token as a Bearer token in the Authorization header:\n    ```\n    Authorization: Bearer YOUR_API_TOKEN\n    ```",
        "operationId": "get_current_user_me_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded — wait Retry-After seconds before retrying",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  },
                  "example": {
                    "detail": "Rate limit exceeded. Please try again later."
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ]
      }
    },
    "/team-invitations/{token}": {
      "get": {
        "tags": [
          "team-invitations"
        ],
        "summary": "Get Team Invitation",
        "description": "Public lookup of a team invitation by token (drives the /invite/{token} page).\n\nNo authentication: the token is an unguessable capability. Returns the\ninvitee email so the registration form can prefill it.",
        "operationId": "get_team_invitation_team_invitations__token__get",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Token"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded — wait Retry-After seconds before retrying",
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "detail": {
                      "type": "string"
                    }
                  },
                  "example": {
                    "detail": "Rate limit exceeded. Please try again later."
                  }
                }
              }
            }
          }
        },
        "security": []
      }
    }
  },
  "components": {
    "schemas": {
      "ChangelogSubscribeRequest": {
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "title": "Email"
          },
          "public_slug": {
            "type": "string",
            "title": "Public Slug"
          }
        },
        "type": "object",
        "required": [
          "email",
          "public_slug"
        ],
        "title": "ChangelogSubscribeRequest"
      },
      "ChangelogSubscribeResponse": {
        "properties": {
          "message": {
            "type": "string",
            "title": "Message"
          }
        },
        "type": "object",
        "required": [
          "message"
        ],
        "title": "ChangelogSubscribeResponse"
      },
      "ChangelogUnsubscribeResponse": {
        "properties": {
          "message": {
            "type": "string",
            "title": "Message"
          }
        },
        "type": "object",
        "required": [
          "message"
        ],
        "title": "ChangelogUnsubscribeResponse"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
          }
        },
        "type": "object",
        "title": "HTTPValidationError"
      },
      "MailingListRead": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "recipient_count": {
            "type": "integer",
            "title": "Recipient Count",
            "default": 0
          },
          "active_count": {
            "type": "integer",
            "title": "Active Count",
            "default": 0
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "created_at"
        ],
        "title": "MailingListRead"
      },
      "RecipientBulkAdd": {
        "properties": {
          "emails": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "maxItems": 1000,
            "minItems": 1,
            "title": "Emails"
          }
        },
        "type": "object",
        "required": [
          "emails"
        ],
        "title": "RecipientBulkAdd"
      },
      "RecipientBulkAddResponse": {
        "properties": {
          "added": {
            "type": "integer",
            "title": "Added"
          },
          "skipped_existing": {
            "type": "integer",
            "title": "Skipped Existing"
          },
          "invalid": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Invalid",
            "default": []
          }
        },
        "type": "object",
        "required": [
          "added",
          "skipped_existing"
        ],
        "title": "RecipientBulkAddResponse"
      },
      "ValidationError": {
        "properties": {
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "type": "array",
            "title": "Location"
          },
          "msg": {
            "type": "string",
            "title": "Message"
          },
          "type": {
            "type": "string",
            "title": "Error Type"
          },
          "input": {
            "title": "Input"
          },
          "ctx": {
            "type": "object",
            "title": "Context"
          }
        },
        "type": "object",
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError"
      }
    },
    "securitySchemes": {
      "HTTPBearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API Token",
        "description": "Enter your API token (created in /dashboard/console)."
      }
    },
    "headers": {
      "RateLimitLimit": {
        "description": "Requests allowed in the current window",
        "schema": {
          "type": "integer"
        },
        "example": 100
      },
      "RateLimitRemaining": {
        "description": "Requests left in the current window",
        "schema": {
          "type": "integer"
        },
        "example": 99
      },
      "RateLimitReset": {
        "description": "Seconds until the window resets",
        "schema": {
          "type": "integer"
        },
        "example": 60
      },
      "RateLimitPolicy": {
        "description": "Quota policy: <limit>;w=<window seconds>",
        "schema": {
          "type": "string"
        },
        "example": "100;w=60"
      },
      "RetryAfter": {
        "description": "Seconds to wait before retrying (on 429)",
        "schema": {
          "type": "integer"
        },
        "example": 60
      }
    }
  },
  "servers": [
    {
      "url": "https://api.shipstar.ai/api/v1",
      "description": "Production"
    }
  ]
}
