{
  "openapi": "3.1.0",
  "info": {
    "title": "Eventi Public API",
    "version": "1.0.0",
    "description": "Eventi sends and tracks event invitations over WhatsApp - delivery, opens, and RSVPs for every guest, with automatic reminders for anyone who has not replied yet. This document covers the public endpoints that need no account: an invitation-card renderer that turns event details into a designed PNG, and a health check.\n\nAuthentication: the public endpoints below need no credentials. They are open to anyone and rate limited by IP. There are no self-serve API keys yet - the rest of the platform (guest lists, sending, RSVP tracking) is session-authenticated through the dashboard at https://app.ueventi.com/login. For the full auth story and what is coming, see https://ueventi.com/auth.md.\n\nRate limits: the invitation renderer allows 30 requests per hour per IP. Over that it returns 429 with a JSON error. Back off and retry after the window resets.\n\nErrors: every error is a JSON object with a machine-readable error string, never an HTML page. Support: support@ueventi.com.",
    "contact": {
      "name": "Eventi",
      "url": "https://ueventi.com",
      "email": "support@ueventi.com"
    }
  },
  "x-service-info": {
    "categories": [
      "events",
      "invitations",
      "rsvp",
      "whatsapp"
    ],
    "docs": "https://ueventi.com/developers",
    "llms": "https://ueventi.com/llms.txt",
    "mcp": "https://ueventi.com/mcp"
  },
  "servers": [
    {
      "url": "https://app.ueventi.com"
    }
  ],
  "paths": {
    "/api/tools/render-invitation": {
      "post": {
        "operationId": "renderInvitationCard",
        "summary": "Render a designed invitation card as a PNG",
        "description": "Turns event details into a designed invitation card and returns it as a PNG image. No authentication is required. CORS is open, so this can be called from a browser. Provide at least an eventName or a title. Rate limited to 30 requests per hour per IP; over that limit the endpoint returns 429.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RenderInvitationRequest"
              },
              "example": {
                "style": "elegant",
                "language": "en",
                "eventType": "wedding",
                "eventName": "Maya & Daniel",
                "title": "Together with their families",
                "bodyText": "We would be delighted to have you celebrate with us.",
                "eventDate": "2026-09-12",
                "venueName": "The Old Vineyard, Napa"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The rendered invitation card.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed - a field was too long, the date was invalid, an enum value was not recognized, or neither eventName nor title was provided.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded - more than 30 requests in the last hour from this IP. Retry after the window resets.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The card could not be generated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "operationId": "getHealth",
        "summary": "Health check",
        "description": "Returns a small JSON object confirming the service is up. No authentication required.",
        "responses": {
          "200": {
            "description": "The service is healthy.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "ok"
                      ]
                    }
                  }
                },
                "example": {
                  "status": "ok"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "RenderInvitationRequest": {
        "type": "object",
        "description": "Event details for the invitation card. Provide at least an eventName or a title; every other field is optional and falls back to a sensible default.",
        "required": [
          "eventName"
        ],
        "properties": {
          "style": {
            "type": "string",
            "enum": [
              "elegant",
              "arch-romance",
              "navy-gold",
              "soft-sky",
              "confetti",
              "modern-ink"
            ],
            "default": "elegant",
            "description": "The visual template. Unrecognized values fall back to elegant."
          },
          "language": {
            "type": "string",
            "enum": [
              "en",
              "he"
            ],
            "default": "en",
            "description": "Card language and text direction. he renders right-to-left Hebrew."
          },
          "eventType": {
            "type": "string",
            "enum": [
              "wedding",
              "bar_mitzvah",
              "engagement",
              "birthday",
              "brit"
            ],
            "default": "wedding",
            "description": "The occasion, which sets the default kicker and closing copy."
          },
          "eventName": {
            "type": "string",
            "maxLength": 80,
            "description": "The headline name on the card, for example the couple's names. At least one of eventName or title is required."
          },
          "title": {
            "type": "string",
            "maxLength": 80,
            "description": "A secondary title or kicker line. Can be supplied instead of eventName."
          },
          "bodyText": {
            "type": "string",
            "maxLength": 220,
            "description": "The body message on the card."
          },
          "eventDate": {
            "type": "string",
            "description": "The event date. Any value parseable as a date is accepted; an unparseable value returns 400."
          },
          "venueName": {
            "type": "string",
            "maxLength": 80,
            "description": "The venue name shown on the card."
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message describing what went wrong."
          }
        }
      }
    }
  }
}