# Legacy REST API Migration Guide

The legacy REST API (`/api/dev/*`) was originally built for third-party integrations. All new integrations should use the [GraphQL Supergraph](https://studio.apollographql.com/public/lavanda-1xwaoq/variant/production/explorer) instead.

This guide maps each legacy endpoint to its GraphQL equivalent.

**Authentication change:** The legacy REST API uses HTTP Basic Auth with an `XX-SUBSCRIPTION-PORTAL-ID` header. The GraphQL API uses OAuth 2.0 bearer tokens — see [Auth](https://docs.lavanda.app/concepts/auth).

**Pagination change:** The legacy REST API uses `perPage` / `limit` offset pagination. GraphQL uses cursor-based pagination (`first`, `after`, max 25 per page) with the [Relay connection pattern](https://docs.lavanda.app/concepts/api-paradigms/connections).

***

## Properties

### `GET /api/dev/properties`

List all properties (units) in the workspace. Supports `perPage`, `last_modified`, and `include` params.

**GraphQL alternative:**

```graphql
query {
  spaces {
    units(filters: { unitTypeId: { in: ["..."] } }, first: 25, after: "cursor") {
      nodes {
        id
        code
        status
        numberOfBedrooms
        numberOfBathrooms
        sizeInSqm
        unitType {
          id
          code
          building { id name }
        }
        amenities { nodes { id name } }
      }
      pageInfo { hasNextPage endCursor }
      totalCount
    }
  }
}
```

> **Note:** The REST endpoint returns "properties" which map to **Units** in the GraphQL schema. There is no `last_modified` filter on the GraphQL query — use webhooks to track changes instead.

***

### `GET /api/dev/properties/:id`

Get a single property by UUID.

**GraphQL alternative:**

```graphql
query {
  spaces {
    unit(id: "uuid") {
      id
      code
      status
      numberOfBedrooms
      numberOfBathrooms
      sizeInSqm
      unitType {
        id
        code
        building { id name address { ... } }
      }
      amenities { nodes { id name } }
      features { nodes { id } }
      mediaItems { nodes { id url } }
    }
  }
}
```

***

### `GET /api/dev/properties/:id/details`

Get detailed property information.

**GraphQL alternative:** Use the same `spaces.unit(id:)` query above and request the fields you need. GraphQL lets you select exactly the fields required instead of receiving a fixed response shape.

***

### `POST /api/dev/properties/:id/rates`

Bulk update rates for a property. Rate-limited to 1 request per minute. Accepts an array of rate objects with `start_date`, `end_date`, `min_night_stay`, and `price`.

**GraphQL alternative:**

```graphql
mutation {
  pricing {
    ratePlans {
      updateRatePlans(input: {
        ratePlans: [
          {
            id: "rate-plan-id"
            minStay: 2
            # ... other rate plan fields
          }
        ]
      }) {
        ratePlans { id }
      }
    }
  }
}
```

Also see `spaces.batchUpdateTariffs` for tariff-level updates:

```graphql
mutation {
  spaces {
    batchUpdateTariffs(input: {
      # tariff update fields
    }) {
      # response
    }
  }
}
```

> **Note:** The rate model differs between the REST and GraphQL APIs. The REST endpoint accepts simple date-range + price pairs, while GraphQL uses rate plans and tariffs. Consult the [Pricing docs](https://docs.lavanda.app/pricing/pricing) for the full model.

***

## Calendar

### `GET /api/dev/properties/:property_id/calendar`

Get calendar/availability data for a property. Supports `start_date`, `end_date`, `limit`, and `perPage`.

**GraphQL alternative:**

```graphql
query {
  availability {
    unitsAvailability(
      q: { ids: ["unit-id"], startDate: "2025-01-01", endDate: "2025-01-31" }
      first: 25
    ) {
      nodes {
        unit { id code }
        availability
      }
      pageInfo { hasNextPage endCursor }
    }
  }
}
```

Or to check a specific unit:

```graphql
query {
  bookings {
    checkUnitAvailability(
      unitId: "unit-id"
      productId: "product-id"
      startDate: "2025-01-01"
      endDate: "2025-01-31"
    ) {
      status
    }
  }
}
```

***

## Account

### `GET /api/dev/account`

Get the current developer/account information.

**GraphQL alternative:**

```graphql
query {
  awc {
    workspace(id: "workspace-id") {
      id
      name
      slug
      status
      logoUrl
    }
  }
}
```

Or to get the authenticated user's info:

```graphql
query {
  authIdentity {
    whoami {
      uuid
      name
      nickname
      status
    }
  }
}
```

***

## Bookings

### `GET /api/dev/bookings`

List bookings with filtering by `property_id`, `start_date`, `end_date`, `limit`, `last_modified`, and `perPage`.

**GraphQL alternative:**

```graphql
query {
  bookings {
    search(
      q: { ids: ["..."] }
      first: 25
      after: "cursor"
    ) {
      nodes {
        id
        confirmationCode
        status
        checkIn
        checkOut
        guests { adults children total }
        guestsCount
        nightsCount
        contacts { nodes { contact { id } role } }
        platform
        product { id name }
        paymentStatus
      }
      pageInfo { hasNextPage endCursor }
      totalCount
    }
  }
}
```

> **Note:** The REST endpoint supports filtering by `property_id` and date ranges. The GraphQL `bookings.search` query currently filters by booking IDs. For broader search capabilities, explore the [API Explorer](https://studio.apollographql.com/public/lavanda-1xwaoq/variant/production/explorer).

***

### `POST /api/dev/bookings/:booking_id/messages`

Send a message to a booking's guest. Accepts `body`, `content_type`, and `source`.

**GraphQL alternative:**

```graphql
mutation {
  conversations {
    sendMessage(input: {
      conversationId: "conversation-id"
      message: "Hello, welcome!"
    }) {
      conversation { id }
    }
  }
}
```

> **Note:** You need the `conversationId` rather than the `bookingId`. Fetch the conversation from the booking first: `bookings.booking(bookingId:) { conversation { id } }`. See [Guest Messaging docs](https://docs.lavanda.app/guest-messaging/general).

***

### `PATCH /api/dev/bookings/:booking_id/guest_verification`

Update guest verification/vetting information. Accepts nested `guest_verification` object with `source`, `external_id`, guest details, and vetting status.

**GraphQL alternative:** There is currently no direct GraphQL mutation for updating guest verification. The vetting status is available as a read-only field on the booking:

```graphql
query {
  bookings {
    booking(bookingId: "booking-id") {
      vetting { status }  # UNVETTED, PENDING, NEEDS_REVIEW, APPROVED, FAILED
    }
  }
}
```

> **Migration status:** A GraphQL mutation for guest verification is not yet available. Continue using the REST endpoint until a replacement is published.

***

## Users

### `GET /api/dev/users`

List users in the workspace. Supports `status` filter, `perPage`, and `include` params.

**GraphQL alternative:**

```graphql
query {
  authIdentity {
    users(first: 25, after: "cursor") {
      nodes {
        id
        email
        name
        nickname
        status
        joinedAt
        roleBindings {
          nodes {
            workspace { id }
            roles { nodes { id name } }
          }
        }
        teams { nodes { id name } }
      }
      pageInfo { hasNextPage endCursor }
      totalCount
    }
  }
}
```

***

## Tasks

### `GET /api/dev/tasks`

List tasks with filtering by `property_id`, `start_date`, `end_date`, `limit`, and `perPage`.

**GraphQL alternative:**

```graphql
query {
  ticketsTasks {
    tasks(first: 25, after: "cursor") {
      nodes {
        id
        title
        type
        dueDate
        startTime
        estimatedDurationHours
        notes
        unit { id code }
        booking { id confirmationCode }
      }
      pageInfo { hasNextPage endCursor }
      totalCount
    }
  }
}
```

> **Note:** The GraphQL query does not currently support filtering by `property_id` or date range at the query level. For advanced filtering, explore the [API Explorer](https://studio.apollographql.com/public/lavanda-1xwaoq/variant/production/explorer).

***

## Webhook Registrations

### `GET /api/dev/webhook_registrations`

List webhook registrations for the workspace.

### `POST /api/dev/webhook_registrations`

Create a new webhook registration. Accepts `notification_url`.

### `DELETE /api/dev/webhook_registrations/:id`

Delete a webhook registration.

**GraphQL alternative:** Webhook management has moved to a dedicated webhooks platform. See [Webhooks](https://docs.lavanda.app/concepts/webhooks) for details on configuring endpoints, which provides retry policies, event filtering, and delivery logs.

> **Migration status:** Contact the customer success team to set up webhook endpoints on the new platform.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.lavanda.app/legacy/dev-api-migration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
