{
  "$schema": "https://plus.solberg.is/schema/manifest.json",
  "site": "noona.is",
  "title": "Noona (noona.is)",
  "description": "Iceland's booking platform: search businesses, list services, check availability, view your bookings — and book/cancel with confirmation and a prepayment guard.",
  "version": "0.1.0",
  "author": "jokull <https://github.com/jokull>",
  "license": "MIT",
  "tags": [
    "bookings",
    "appointments",
    "health"
  ],
  "identities": [
    "customer"
  ],
  "auth": [
    {
      "id": "otp-token",
      "type": "otp-token",
      "description": "Phone number + SMS code → long-lived HS256 JWT (issued per phone number, effectively non-expiring). Store the token in the keychain, not a plaintext file.",
      "default": true,
      "probe": "GET /user returns the profile",
      "credentials": [
        "NOONA_TOKEN"
      ]
    }
  ],
  "ops": [
    {
      "id": "search",
      "kind": "rest",
      "title": "Search businesses",
      "description": "Search enterprises by name/query.",
      "tags": [
        "search"
      ],
      "risk": "read-only",
      "input": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string"
          }
        },
        "required": [
          "query"
        ]
      },
      "output": {
        "$ref": "#/schemas/Enterprise"
      }
    },
    {
      "id": "services",
      "kind": "rest",
      "title": "List services",
      "description": "Event types (services) for a company, with price and prepayment requirements.",
      "tags": [
        "services"
      ],
      "risk": "read-only",
      "input": {
        "type": "object",
        "properties": {
          "companyId": {
            "type": "string"
          }
        },
        "required": [
          "companyId"
        ]
      },
      "output": {
        "$ref": "#/schemas/EventType"
      }
    },
    {
      "id": "availability",
      "kind": "rest",
      "title": "Check availability",
      "description": "Time slots for a company + event type over a date range.",
      "tags": [
        "availability"
      ],
      "risk": "read-only",
      "input": {
        "type": "object",
        "properties": {
          "companyId": {
            "type": "string"
          },
          "eventTypeId": {
            "type": "string"
          },
          "startDate": {
            "type": "string",
            "format": "date"
          },
          "days": {
            "type": "integer",
            "minimum": 1,
            "maximum": 30,
            "default": 7
          }
        },
        "required": [
          "companyId",
          "eventTypeId"
        ]
      },
      "output": {
        "$ref": "#/schemas/TimeSlotDay"
      }
    },
    {
      "id": "bookings",
      "kind": "rest",
      "title": "My bookings",
      "description": "Upcoming bookings (events) with service, company, employee, price and status.",
      "tags": [
        "bookings"
      ],
      "risk": "read-only",
      "input": {
        "type": "object",
        "properties": {
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 20
          }
        }
      },
      "output": {
        "$ref": "#/schemas/Booking"
      }
    },
    {
      "id": "book",
      "kind": "rest",
      "title": "Book a slot",
      "description": "Two-step: create time_slot_reservation, then confirm into an event. Refuses services that require prepayment (avoids accidental charges). Mutating.",
      "tags": [
        "bookings"
      ],
      "risk": "mutating",
      "confirm": true,
      "idempotent": false,
      "dryRun": true,
      "input": {
        "type": "object",
        "properties": {
          "companyId": {
            "type": "string"
          },
          "eventTypeId": {
            "type": "string"
          },
          "startsAt": {
            "type": "string",
            "format": "date-time"
          },
          "employeeId": {
            "type": "string"
          }
        },
        "required": [
          "companyId",
          "eventTypeId",
          "startsAt"
        ]
      },
      "output": {
        "$ref": "#/schemas/Booking"
      }
    },
    {
      "id": "cancel",
      "kind": "rest",
      "title": "Cancel a booking",
      "description": "Cancel an event by id. Mutating.",
      "tags": [
        "bookings"
      ],
      "risk": "mutating",
      "confirm": true,
      "idempotent": true,
      "input": {
        "type": "object",
        "properties": {
          "eventId": {
            "type": "string"
          }
        },
        "required": [
          "eventId"
        ]
      },
      "output": {
        "$ref": "#/schemas/Booking"
      }
    }
  ],
  "schemas": {
    "Enterprise": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "profile": {
          "type": "object",
          "properties": {
            "name": {
              "type": "string"
            }
          }
        },
        "companies": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              }
            }
          }
        }
      }
    },
    "EventType": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "title": {
          "type": "string"
        },
        "minutes": {
          "type": "integer"
        },
        "payments": {
          "type": "object",
          "properties": {
            "total_payment": {
              "type": "number"
            },
            "pre_payment_required": {
              "type": "boolean"
            },
            "pre_payment_amount": {
              "type": "number"
            }
          }
        }
      }
    },
    "TimeSlotDay": {
      "type": "object",
      "properties": {
        "date": {
          "type": "string",
          "format": "date"
        },
        "slots": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "time": {
                "type": "string"
              },
              "employeeIds": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "Booking": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "starts_at": {
          "type": "string",
          "format": "date-time"
        },
        "ends_at": {
          "type": "string",
          "format": "date-time"
        },
        "confirmed": {
          "type": "boolean"
        },
        "status": {
          "type": "string"
        },
        "event_types": {
          "type": "array",
          "items": {
            "type": "object"
          }
        },
        "company": {
          "type": "object"
        },
        "employee": {
          "type": "object"
        },
        "payments": {
          "type": "object"
        }
      }
    }
  },
  "origins": [
    "https://noona.is",
    "https://api.noona.is"
  ]
}
