{
  "openapi": "3.0.3",
  "info": {
    "title": "Mati API v1",
    "description": "Booking, scheduling and payments API for developers building with Mati.",
    "version": "1.0.0",
    "contact": {
      "name": "Mati Developer Support",
      "url": "https://app.mati-ia.com/developers"
    }
  },
  "servers": [
    {
      "url": "https://app.mati-ia.com/api/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "paths": {
    "/workspaces/{slug}": {
      "get": {
        "summary": "Get workspace",
        "description": "Returns public workspace metadata. Requires an API key for developer backends.",
        "operationId": "getWorkspace",
        "tags": [
          "Workspaces"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Slug"
          }
        ],
        "responses": {
          "200": {
            "description": "Workspace details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/workspaces/{slug}/services": {
      "get": {
        "summary": "List services",
        "description": "Returns active services for a workspace.",
        "operationId": "listServices",
        "tags": [
          "Services"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Slug"
          }
        ],
        "responses": {
          "200": {
            "description": "List of services",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServicesResponse"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/workspaces/{slug}/config": {
      "get": {
        "summary": "Get widget config",
        "description": "Public endpoint used by the widget to load workspace settings and custom fields.",
        "operationId": "getWidgetConfig",
        "tags": [
          "Widget"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Slug"
          }
        ],
        "responses": {
          "200": {
            "description": "Widget configuration",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WidgetConfigResponse"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/workspaces/{slug}/bookings": {
      "get": {
        "summary": "List bookings",
        "description": "Returns recent bookings for the workspace. Paginated (max 100 per page).",
        "operationId": "listBookings",
        "tags": [
          "Bookings"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Slug"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Opaque cursor returned by the previous page (cursor-based pagination)"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "PENDING",
                "CONFIRMED",
                "CANCELLED",
                "COMPLETED"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of bookings",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/BookingsResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "nextCursor": {
                          "type": "string",
                          "nullable": true
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "post": {
        "summary": "Create booking",
        "description": "Creates a new booking. Can be called either with an API key (backend-to-backend) or from an authorized widget domain (public).",
        "operationId": "createBooking",
        "tags": [
          "Bookings"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Slug"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BookingCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Booking created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BookingResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-mati-api-key",
        "description": "Workspace API key. Available in the Mati dashboard under Settings > API Keys."
      }
    },
    "parameters": {
      "Slug": {
        "name": "slug",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "Workspace slug"
      },
      "WebhookId": {
        "name": "webhookId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "Webhook ID"
      }
    },
    "schemas": {
      "Workspace": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "primaryColor": {
            "type": "string",
            "nullable": true
          },
          "plan": {
            "type": "string"
          },
          "industry": {
            "type": "string"
          },
          "timezone": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "timeFormat": {
            "type": "string"
          },
          "cancellationHours": {
            "type": "number"
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "plan",
          "industry",
          "timezone",
          "language",
          "timeFormat",
          "cancellationHours"
        ]
      },
      "WorkspaceResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "workspace": {
            "$ref": "#/components/schemas/Workspace"
          }
        },
        "required": [
          "success",
          "workspace"
        ]
      },
      "Service": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "duration": {
            "type": "integer"
          },
          "price": {
            "type": "number"
          },
          "currency": {
            "type": "string"
          },
          "active": {
            "type": "boolean"
          },
          "category": {
            "type": "string",
            "nullable": true
          },
          "capacity": {
            "type": "integer"
          },
          "bufferTime": {
            "type": "integer"
          },
          "minNotice": {
            "type": "integer"
          },
          "maxAdvance": {
            "type": "integer",
            "nullable": true
          },
          "deposit": {
            "type": "number",
            "nullable": true
          },
          "order": {
            "type": "integer"
          }
        },
        "required": [
          "id",
          "name",
          "duration",
          "price",
          "currency",
          "active",
          "capacity",
          "bufferTime",
          "minNotice",
          "order"
        ]
      },
      "ServicesResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "services": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Service"
            }
          }
        },
        "required": [
          "success",
          "services"
        ]
      },
      "Booking": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "startTime": {
            "type": "string",
            "format": "date-time"
          },
          "endTime": {
            "type": "string",
            "format": "date-time"
          },
          "status": {
            "type": "string"
          },
          "customerName": {
            "type": "string",
            "nullable": true
          },
          "customerEmail": {
            "type": "string"
          },
          "serviceName": {
            "type": "string",
            "nullable": true
          },
          "providerName": {
            "type": "string",
            "nullable": true
          },
          "amount": {
            "type": "number",
            "nullable": true
          }
        },
        "required": [
          "id",
          "startTime",
          "endTime",
          "status",
          "customerEmail"
        ]
      },
      "BookingCreate": {
        "type": "object",
        "properties": {
          "serviceId": {
            "type": "string"
          },
          "providerId": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "name": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "duration": {
            "type": "integer",
            "minimum": 5
          },
          "notes": {
            "type": "string"
          },
          "recaptchaToken": {
            "type": "string"
          }
        },
        "required": [
          "serviceId",
          "email",
          "date"
        ]
      },
      "BookingResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "checkoutUrl": {
            "type": "string",
            "nullable": true
          },
          "booking": {
            "$ref": "#/components/schemas/Booking"
          }
        },
        "required": [
          "success",
          "booking"
        ]
      },
      "BookingsResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "bookings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Booking"
            }
          }
        },
        "required": [
          "success",
          "bookings"
        ]
      },
      "WidgetConfigResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "workspace": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "primaryColor": {
                "type": "string",
                "nullable": true
              }
            },
            "required": [
              "id",
              "name"
            ]
          },
          "customFields": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        },
        "required": [
          "success",
          "workspace",
          "customFields"
        ]
      },
      "AvailabilityResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "slots": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Available times in HH:mm format, workspace timezone"
          },
          "timezone": {
            "type": "string"
          }
        },
        "required": [
          "success",
          "slots",
          "timezone"
        ]
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "secret": {
            "type": "string",
            "description": "HMAC-SHA256 secret — only shown once on creation"
          },
          "isActive": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Event types this webhook subscribes to. Empty = all events."
          }
        },
        "required": [
          "id",
          "url",
          "isActive",
          "createdAt"
        ]
      },
      "WebhookCreate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Filter specific event types (booking.created, booking.confirmed, etc). Empty = all.",
            "example": [
              "booking.created",
              "payment.received"
            ]
          }
        },
        "required": [
          "url"
        ]
      },
      "WebhookResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "webhook": {
            "$ref": "#/components/schemas/Webhook"
          }
        },
        "required": [
          "success",
          "webhook"
        ]
      },
      "WebhooksResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "webhooks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Webhook"
            }
          }
        },
        "required": [
          "success",
          "webhooks"
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "error": {
            "type": "string"
          },
          "code": {
            "type": "string"
          }
        },
        "required": [
          "success",
          "error"
        ]
      }
    },
    "headers": {
      "RateLimitLimit": {
        "description": "Total requests per minute allowed for this key",
        "schema": {
          "type": "integer",
          "example": 120
        }
      },
      "RateLimitRemaining": {
        "description": "Requests remaining in the current window",
        "schema": {
          "type": "integer",
          "example": 87
        }
      },
      "RateLimitReset": {
        "description": "Unix timestamp when the limit window resets",
        "schema": {
          "type": "integer",
          "format": "int64",
          "example": 1785460233
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Unauthorized",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Forbidden",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ValidationError": {
        "description": "Validation error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many requests — rate limit exceeded",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          },
          "Retry-After": {
            "description": "Seconds to wait before retrying",
            "schema": {
              "type": "integer",
              "example": 30
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "success": false,
              "error": "Rate limit exceeded. Try again in 30 seconds.",
              "code": "RATE_LIMITED"
            }
          }
        }
      }
    }
  }
}