{
  "openapi": "3.0.3",
  "info": {
    "title": "Jot Transcribe API",
    "description": "API for Jot Transcribe donations, feedback, and transparency features.",
    "version": "2.0.0",
    "contact": {
      "name": "Jot Transcribe",
      "email": "jottranscribe@gmail.com"
    }
  },
  "servers": [
    {
      "url": "https://donations.jot-transcribe.com",
      "description": "Production"
    }
  ],
  "paths": {
    "/summary": {
      "get": {
        "summary": "Get donation summary",
        "description": "Returns aggregated donation totals per charity with metadata (description, logo, fundraiser URL).",
        "operationId": "getDonationSummary",
        "tags": [
          "Donations"
        ],
        "responses": {
          "200": {
            "description": "Donation summary",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DonationSummary"
                }
              }
            }
          },
          "500": {
            "description": "Database error"
          }
        }
      }
    },
    "/feedback": {
      "post": {
        "summary": "Submit feedback",
        "description": "Submit feedback from iOS or macOS app. Supports optional base64-encoded screenshot images.",
        "operationId": "submitFeedback",
        "tags": [
          "Feedback"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeedbackRequest"
              },
              "example": {
                "platform": "ios",
                "version": "1.2.0",
                "message": "The transcription stopped working after iOS update.",
                "images": [
                  "data:image/png;base64,iVBORw0KGgo..."
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Feedback submitted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedbackResponse"
                },
                "example": {
                  "status": "ok",
                  "id": 42
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedbackResponse"
                },
                "example": {
                  "status": "error",
                  "error": "Missing required fields: platform, version, message"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (5 requests per minute per IP)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedbackResponse"
                },
                "example": {
                  "status": "error",
                  "error": "Rate limit exceeded. Please try again later."
                }
              }
            }
          }
        }
      }
    },
    "/feedback/list": {
      "get": {
        "summary": "List feedback",
        "description": "Returns the 100 most recent feedback entries with images.",
        "operationId": "listFeedback",
        "tags": [
          "Feedback"
        ],
        "responses": {
          "200": {
            "description": "List of feedback entries",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Feedback"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Database error"
          }
        }
      }
    },
    "/webhook": {
      "post": {
        "summary": "Receive donation webhook",
        "description": "Receives webhook notifications from Every.org when a donation is made.",
        "operationId": "receiveDonationWebhook",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "webhookToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EveryOrgWebhook"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook received successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "example": "ok"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing webhook token"
          },
          "429": {
            "description": "Rate limited"
          }
        }
      }
    },
    "/healthz": {
      "get": {
        "summary": "Health check",
        "description": "Returns service health status.",
        "operationId": "healthCheck",
        "tags": [
          "System"
        ],
        "responses": {
          "200": {
            "description": "Service is healthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthStatus"
                }
              }
            }
          },
          "503": {
            "description": "Service is unhealthy"
          }
        }
      }
    },
    "/charities.json": {
      "get": {
        "summary": "Get charity configuration",
        "description": "Returns the list of configured charities with metadata.",
        "operationId": "getCharities",
        "tags": [
          "Donations"
        ],
        "responses": {
          "200": {
            "description": "Charity configuration",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CharitiesConfig"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "webhookToken": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Webhook-Token",
        "description": "Webhook token from Every.org partner dashboard"
      }
    },
    "schemas": {
      "DonationSummary": {
        "type": "object",
        "properties": {
          "total_donations": {
            "type": "integer",
            "description": "Total number of donations"
          },
          "total_raised_usd": {
            "type": "number",
            "description": "Total amount raised in USD"
          },
          "per_charity": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CharitySummary"
            }
          },
          "last_updated": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CharitySummary": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "description": "Nonprofit slug",
            "example": "roomtoread"
          },
          "name": {
            "type": "string",
            "description": "Nonprofit display name",
            "example": "Room to Read"
          },
          "description": {
            "type": "string",
            "description": "Brief description of the charity",
            "example": "Promotes literacy and girls' education in low-income communities."
          },
          "fundraiser_url": {
            "type": "string",
            "format": "uri",
            "description": "Link to donate to this charity",
            "example": "https://www.every.org/roomtoread/f/literacy-and-girls-education"
          },
          "logo_url": {
            "type": "string",
            "format": "uri",
            "description": "Charity logo image URL (200x200)",
            "example": "https://res.cloudinary.com/everydotorg/image/upload/..."
          },
          "count": {
            "type": "integer",
            "description": "Number of donations"
          },
          "total_raised_usd": {
            "type": "number",
            "description": "Total raised in USD"
          }
        }
      },
      "FeedbackRequest": {
        "type": "object",
        "required": [
          "platform",
          "version",
          "message"
        ],
        "properties": {
          "platform": {
            "type": "string",
            "enum": [
              "ios",
              "macos"
            ],
            "description": "App platform"
          },
          "version": {
            "type": "string",
            "description": "App version number",
            "example": "1.2.0"
          },
          "message": {
            "type": "string",
            "description": "Feedback message (max 10KB)",
            "maxLength": 10240
          },
          "images": {
            "type": "array",
            "description": "Base64-encoded images (max 3, max 5MB total)",
            "maxItems": 3,
            "items": {
              "type": "string",
              "description": "Base64 data URI (e.g., data:image/png;base64,...)"
            }
          }
        }
      },
      "FeedbackResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "error"
            ]
          },
          "id": {
            "type": "integer",
            "description": "Feedback ID (only on success)"
          },
          "error": {
            "type": "string",
            "description": "Error message (only on error)"
          }
        }
      },
      "Feedback": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "platform": {
            "type": "string",
            "enum": [
              "ios",
              "macos"
            ]
          },
          "version": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "images": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Base64-encoded images"
          },
          "ip": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "EveryOrgWebhook": {
        "type": "object",
        "required": [
          "chargeId",
          "toNonprofit",
          "amount",
          "netAmount"
        ],
        "properties": {
          "chargeId": {
            "type": "string",
            "description": "Unique donation ID from Every.org"
          },
          "partnerDonationId": {
            "type": "string"
          },
          "toNonprofit": {
            "type": "object",
            "properties": {
              "slug": {
                "type": "string"
              },
              "ein": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            }
          },
          "amount": {
            "type": "string"
          },
          "netAmount": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "frequency": {
            "type": "string",
            "enum": [
              "One-time",
              "Monthly",
              "Yearly"
            ]
          },
          "donationDate": {
            "type": "string",
            "format": "date"
          }
        }
      },
      "CharitiesConfig": {
        "type": "object",
        "properties": {
          "charities": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "slug": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                },
                "fundraiser_url": {
                  "type": "string",
                  "format": "uri"
                },
                "logo_url": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          }
        }
      },
      "HealthStatus": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "healthy",
              "unhealthy"
            ]
          },
          "db": {
            "type": "string",
            "enum": [
              "up",
              "down"
            ]
          }
        }
      }
    }
  }
}
