{
  "openapi": "3.1.0",
  "info": {
    "title": "Tap2Cal API",
    "version": "1.0.0",
    "description": "Create shareable add-to-calendar links. Event pages are public to anyone with the link and are deleted 90 days after the event ends. Accounts can create up to 50 events per day."
  },
  "servers": [{"url": "https://tap2cal.com/api/v1"}],
  "security": [{"apiKey": []}],
  "paths": {
    "/events": {
      "post": {
        "operationId": "createEvent",
        "summary": "Create an event and its shareable link",
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/NewEvent"}}}
        },
        "responses": {
          "201": {
            "description": "Event created",
            "content": {"application/json": {"schema": {
              "type": "object",
              "properties": {"event": {"$ref": "#/components/schemas/Event"}}
            }}}
          },
          "400": {"$ref": "#/components/responses/Error"},
          "401": {"$ref": "#/components/responses/Error"},
          "429": {"$ref": "#/components/responses/Error"}
        }
      },
      "get": {
        "operationId": "listEvents",
        "summary": "List the events of this account, up to 100",
        "responses": {
          "200": {
            "description": "Events of this account",
            "content": {"application/json": {"schema": {
              "type": "object",
              "properties": {"events": {"type": "array", "items": {"$ref": "#/components/schemas/Event"}}}
            }}}
          },
          "401": {"$ref": "#/components/responses/Error"}
        }
      }
    },
    "/events/{id}/flyer": {
      "post": {
        "operationId": "uploadFlyer",
        "summary": "Add a flyer to an event, shown on its page and in link previews",
        "description": "Send the image file as the request body, up to 8 MB. Images are checked automatically before they are published.",
        "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}],
        "requestBody": {
          "required": true,
          "content": {"application/octet-stream": {"schema": {"type": "string", "format": "binary"}}}
        },
        "responses": {
          "200": {
            "description": "Flyer saved",
            "content": {"application/json": {"schema": {
              "type": "object",
              "properties": {"event": {"$ref": "#/components/schemas/Event"}}
            }}}
          },
          "400": {"$ref": "#/components/responses/Error"},
          "401": {"$ref": "#/components/responses/Error"},
          "404": {"$ref": "#/components/responses/Error"},
          "413": {"$ref": "#/components/responses/Error"},
          "422": {"$ref": "#/components/responses/Error"},
          "429": {"$ref": "#/components/responses/Error"}
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {"type": "http", "scheme": "bearer", "description": "API key from https://tap2cal.com/app/account"}
    },
    "responses": {
      "Error": {
        "description": "Error with a code such as invalid_date or too_many_events",
        "content": {"application/json": {"schema": {
          "type": "object",
          "properties": {"error": {"type": "string"}}
        }}}
      }
    },
    "schemas": {
      "NewEvent": {
        "type": "object",
        "required": ["name", "startDate", "timeZone"],
        "properties": {
          "name": {"type": "string", "maxLength": 120},
          "startDate": {"type": "string", "format": "date"},
          "endDate": {"type": "string", "format": "date", "description": "Defaults to the start date"},
          "startTime": {"type": "string", "example": "18:00", "description": "HH:MM. Leave out for an all-day event"},
          "endTime": {"type": "string", "example": "22:00", "description": "HH:MM. Required with a start time"},
          "timeZone": {"type": "string", "example": "Europe/Vienna"},
          "location": {"type": "string", "maxLength": 200},
          "subtitle": {"type": "string", "maxLength": 160},
          "description": {"type": "string", "maxLength": 1000},
          "link": {"type": "string", "format": "uri", "maxLength": 500},
          "accentColor": {"type": "string", "example": "#0f7b63"},
          "backgroundColor": {"type": "string", "example": "#f5f7f8"},
          "lang": {"type": "string", "enum": ["en", "de", "es", "fr", "it", "pt"], "description": "Language of the link preview"}
        }
      },
      "Event": {
        "type": "object",
        "properties": {
          "id": {"type": "string"},
          "url": {"type": "string", "format": "uri", "description": "The link to share"},
          "name": {"type": "string"},
          "location": {"type": ["string", "null"]},
          "startDate": {"type": "string", "format": "date"},
          "endDate": {"type": "string", "format": "date"},
          "startTime": {"type": ["string", "null"]},
          "endTime": {"type": ["string", "null"]},
          "allDay": {"type": "boolean"},
          "timeZone": {"type": "string"},
          "lang": {"type": ["string", "null"]},
          "subtitle": {"type": ["string", "null"]},
          "description": {"type": ["string", "null"]},
          "link": {"type": ["string", "null"]},
          "accentColor": {"type": ["string", "null"]},
          "backgroundColor": {"type": ["string", "null"]},
          "flyerUrl": {"type": ["string", "null"]},
          "viewCount": {"type": "integer"},
          "calendarClicks": {"type": "object", "additionalProperties": {"type": "integer"}},
          "deletesOn": {"type": "string", "format": "date"}
        }
      }
    }
  }
}
