# Tell&Go Universal Agent API Documentation

> Complete reference for the Tell&Go Universal Agent API. Search properties, check availability, and create bookings programmatically.

**Base URL:** `https://api.tellandgo.com/api/v1/agent`

**Version:** 1.0.0

---

## Table of Contents

- [Authentication](#authentication)
- [Rate Limits](#rate-limits)
- [Endpoints](#endpoints)
  - [Search Properties](#search-properties)
  - [Get Property Details](#get-property-details)
  - [Check Availability](#check-availability)
  - [Agentic Chat](#agentic-chat)
  - [Create Quote](#create-quote)
  - [Prebook Quote](#prebook-quote)
  - [Create Booking](#create-booking)
  - [List Bookings](#list-bookings)
  - [Get Booking Details](#get-booking-details)
  - [Cancel Booking](#cancel-booking)
- [Error Handling](#error-handling)
- [Code Examples](#code-examples)

---

## Authentication

All API requests require authentication using an API key passed in the `X-API-Key` header.

### API Key Types

| Key Prefix  | Environment | Description                                                  |
| ----------- | ----------- | ------------------------------------------------------------ |
| `tg_live_*` | Production  | Use for live production applications. Real data and billing. |
| `tg_test_*` | Sandbox     | Use for development and testing. No real bookings created.   |

### Example Request

```bash
curl -H "X-API-Key: tg_live_your_api_key" \
  https://api.tellandgo.com/api/v1/agent/search
```

---

## Rate Limits

API requests are rate limited based on your subscription tier.

| Tier       | Rate Limit   | Commission |
| ---------- | ------------ | ---------- |
| Free       | 100/hour     | 2-3.5%     |
| Enterprise | 10,000+/hour | Custom     |

Rate limit headers are included in every response:

- `X-RateLimit-Limit`: Your rate limit ceiling
- `X-RateLimit-Remaining`: Remaining requests in current window
- `X-RateLimit-Reset`: Unix timestamp when the limit resets

---

## Endpoints

### Search Properties

Search for properties using natural language queries. This endpoint performs live accommodation pricing for every valid request. Provide dates, residency, and occupancy; identical RateHawk SERP requests may be served from the 5-minute supplier cache.

**Endpoint:** `POST /search`

#### Request Body

| Field                         | Type     | Required | Description                                                                                                   |
| ----------------------------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------- |
| `query`                       | string   | Yes      | Natural language search query                                                                                 |
| `residency`                   | string   | Yes      | ISO 3166-1 alpha-2 citizenship/residency code. Sent to live supplier searches as `residency`.                 |
| `constraints`                 | object   | Yes      | Search constraints containing dates and either guests or rooms.                                               |
| `constraints.destination`     | string   | No       | Target destination or country                                                                                 |
| `constraints.budget_min`      | number   | No       | Minimum budget per night (USD)                                                                                |
| `constraints.budget_max`      | number   | No       | Maximum budget per night (USD)                                                                                |
| `constraints.dates`           | object   | Yes      | Check-in and check-out dates. Required for live supplier pricing.                                             |
| `constraints.dates.check_in`  | string   | Yes      | Check-in date (YYYY-MM-DD).                                                                                   |
| `constraints.dates.check_out` | string   | Yes      | Check-out date (YYYY-MM-DD).                                                                                  |
| `constraints.guests`          | object   | Yes\*    | Single-room/simple occupancy. Use `constraints.rooms` for multi-room live pricing.                            |
| `constraints.guests.adults`   | number   | No       | Number of adults.                                                                                             |
| `constraints.guests.children` | number[] | No       | Child ages.                                                                                                   |
| `constraints.rooms`           | array    | Yes\*    | Per-room occupancy for multi-room live pricing. Each room has `adults` and optional child ages in `children`. |
| `constraints.amenities`       | string[] | No       | Required amenities                                                                                            |
| `constraints.activities`      | string[] | No       | Activities or travel interests                                                                                |
| `limit`                       | number   | No       | Maximum results (default: 10, max: 50)                                                                        |
| `offset`                      | number   | No       | Pagination offset (default: 0)                                                                                |

\* Provide either `constraints.guests` or `constraints.rooms`.

#### Example Request

```json
{
  "query": "luxury beach resort in maldives with overwater villas",
  "residency": "US",
  "constraints": {
    "destination": "maldives",
    "budget_min": 500,
    "budget_max": 2000,
    "dates": {
      "check_in": "2026-08-01",
      "check_out": "2026-08-07"
    },
    "guests": {
      "adults": 2,
      "children": []
    },
    "amenities": ["spa", "pool", "restaurant"]
  },
  "limit": 10
}
```

#### Example Response

```json
{
  "success": true,
  "properties": [
    {
      "id": "clx123abc",
      "name": "Soneva Fushi",
      "location": {
        "country": "Maldives",
        "area": "Baa Atoll"
      },
      "rating": 4.9,
      "match": {
        "score": 92,
        "explanation": "Exceptional luxury resort in Baa Atoll with overwater villas"
      },
      "highlights": ["56 villas", "6 restaurants", "Award-winning spa"],
      "price_from": 1200
    }
  ],
  "pagination": {
    "total": 45,
    "has_more": true
  }
}
```

#### cURL Example

```bash
curl -X POST https://api.tellandgo.com/api/v1/agent/search \
  -H "X-API-Key: tg_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "luxury beach resort in maldives with overwater villas",
    "residency": "US",
    "limit": 10
  }'
```

---

### Get Property Details

Retrieve detailed information about a specific property.

**Endpoint:** `GET /properties/:id`

#### Path Parameters

| Parameter | Type   | Required | Description                    |
| --------- | ------ | -------- | ------------------------------ |
| `id`      | string | Yes      | The unique property identifier |

#### Example Response

```json
{
  "success": true,
  "property": {
    "id": "clx123abc",
    "name": "Soneva Fushi",
    "description": "Award-winning luxury resort in the Maldives featuring 56 private villas...",
    "location": {
      "country": "Maldives",
      "area": "Baa Atoll",
      "address": "Kunfunadhoo Island"
    },
    "amenities": [
      { "name": "Spa", "category": "wellness" },
      { "name": "Infinity Pool", "category": "recreation" },
      { "name": "Private Beach", "category": "beach" }
    ],
    "dining": [
      { "name": "Fresh in the Garden", "cuisine": "Organic" },
      { "name": "Out of the Blue", "cuisine": "Seafood" }
    ],
    "rating": 4.9,
    "room_count": 56
  },
  "booking_url": "https://tellandgo.com/properties/soneva-fushi?ref=partner"
}
```

#### cURL Example

```bash
curl https://api.tellandgo.com/api/v1/agent/properties/clx123abc \
  -H "X-API-Key: tg_live_your_api_key"
```

---

### Check Availability

Check real-time availability and pricing for a property.

**Endpoint:** `POST /availability`

#### Request Body

| Field             | Type     | Required | Description                                                                         |
| ----------------- | -------- | -------- | ----------------------------------------------------------------------------------- |
| `property_id`     | string   | Yes      | Property ID                                                                         |
| `check_in`        | string   | Yes      | Check-in date (YYYY-MM-DD)                                                          |
| `check_out`       | string   | Yes      | Check-out date (YYYY-MM-DD)                                                         |
| `guests`          | object   | No       | Single-room/simple occupancy object. For multi-room searches, send `rooms` instead. |
| `guests.adults`   | number   | No       | Number of adults. Required only when `rooms` is omitted.                            |
| `guests.children` | number[] | No       | Array of children ages                                                              |
| `rooms`           | array    | No       | Per-room occupancy for multi-room searches. Required when `guests` is omitted.      |

#### Example Request

```json
{
  "property_id": "clx123abc",
  "check_in": "2025-03-01",
  "check_out": "2025-03-07",
  "guests": {
    "adults": 2,
    "children": [10, 8]
  }
}
```

#### Example Response

```json
{
  "available": true,
  "rooms": [
    {
      "id": "room_456",
      "name": "Crusoe Villa with Pool",
      "description": "Beachfront villa with private pool",
      "max_occupancy": 4,
      "rates": [
        {
          "rate_plan": "Best Available Rate",
          "price_per_night": 1500,
          "total_price": 9000,
          "currency": "USD",
          "includes": ["Breakfast", "Airport transfers"]
        }
      ]
    }
  ],
  "hotel_policies": {
    "extra_info": "A local tourist tax may be charged during the stay and paid at the hotel.",
    "structured": {
      "pets": [
        {
          "price": "100.00",
          "currency": "USD",
          "inclusion": "not_included",
          "price_unit": "per_room_per_stay"
        }
      ],
      "deposit": []
    }
  }
}
```

`hotel_policies` is supplier-neutral. Use `hotel_policies.extra_info` for free-text policy notes and `hotel_policies.structured` for structured policy data. Supplier-specific raw field names are not exposed.

#### cURL Example

```bash
curl -X POST https://api.tellandgo.com/api/v1/agent/availability \
  -H "X-API-Key: tg_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "property_id": "clx123abc",
    "check_in": "2025-03-01",
    "check_out": "2025-03-07",
    "residency": "US",
    "rooms": [
      { "adults": 1, "children": [0, 17] },
      { "adults": 1, "children": [10] }
    ]
  }'
```

Use `rooms` as the occupancy source for multi-room availability searches. Top-level `guests` remains supported for single-room/simple requests and backward compatibility, but it is not required when `rooms` is provided.

---

### Agentic Chat

Conversational endpoint for AI-powered property discovery with follow-up questions.

**Endpoint:** `POST /chat`

**Version:** V2

#### Request Body

| Field                           | Type    | Required | Description                                |
| ------------------------------- | ------- | -------- | ------------------------------------------ |
| `message`                       | string  | Yes      | User message                               |
| `session_id`                    | string  | No       | Session ID for conversation continuity     |
| `context`                       | object  | No       | Previously collected preferences           |
| `context.previous_searches`     | array   | No       | Prior searches in the session              |
| `context.selected_properties`   | array   | No       | Properties already selected or viewed      |
| `context.collected_preferences` | object  | No       | Structured preferences collected so far    |
| `include_pricing`               | boolean | No       | Include pricing where available            |
| `max_properties`                | number  | No       | Maximum property recommendations to return |
| `max_follow_ups`                | number  | No       | Maximum follow-up questions to return      |

#### Example Request

```json
{
  "message": "I'm looking for a romantic honeymoon destination",
  "session_id": "session_xxx",
  "context": {
    "collected_preferences": {
      "travel_style": ["romantic"]
    }
  }
}
```

#### Example Response

```json
{
  "response": {
    "text": "I found some beautiful honeymoon destinations for you. Based on your preferences, I'd recommend these romantic properties...",
    "intent": "recommendation"
  },
  "properties": [
    {
      "id": "clx123abc",
      "name": "Soneva Fushi",
      "match": { "score": 95 }
    }
  ],
  "follow_ups": [
    {
      "question": "What's your budget per night?",
      "options": [
        { "label": "$500-1000", "value": "500-1000" },
        { "label": "$1000-2000", "value": "1000-2000" },
        { "label": "$2000+", "value": "2000+" }
      ]
    }
  ],
  "session_id": "session_xxx"
}
```

#### cURL Example

```bash
curl -X POST https://api.tellandgo.com/api/v1/agent/chat \
  -H "X-API-Key: tg_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "I am looking for a romantic honeymoon destination",
    "session_id": "session_xxx"
  }'
```

---

### Create Quote

Generate a bookable pricing quote with a 15-minute validity window.

**Endpoint:** `POST /quote`

**Version:** V2

#### Request Body

| Field             | Type     | Required | Description                                                                                                                                |
| ----------------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `property_id`     | string   | Yes      | Property ID                                                                                                                                |
| `check_in`        | string   | Yes      | Check-in date (YYYY-MM-DD)                                                                                                                 |
| `check_out`       | string   | Yes      | Check-out date (YYYY-MM-DD)                                                                                                                |
| `guests`          | object   | No       | Single-room/simple occupancy object. For multi-room quotes, send `rooms` instead.                                                          |
| `guests.adults`   | number   | No       | Number of adults. Required only when `rooms` is omitted.                                                                                   |
| `guests.children` | number[] | No       | Child ages                                                                                                                                 |
| `rooms`           | array    | No       | Per-room occupancy for multi-room quotes. Required when `guests` is omitted. Each room has `adults` and optional child ages in `children`. |
| `residency`       | string   | Yes      | ISO 3166-1 alpha-2 citizenship/residency code for live pricing                                                                             |
| `room_id`         | string   | No       | Room ID from availability. If omitted, the best matching room/rate is selected.                                                            |
| `rate_plan`       | string   | No       | Rate plan identifier from availability                                                                                                     |

#### Example Request

```json
{
  "property_id": "clx123abc",
  "room_id": "room_456",
  "check_in": "2025-03-01",
  "check_out": "2025-03-07",
  "residency": "US",
  "rooms": [
    { "adults": 1, "children": [0, 17] },
    { "adults": 1, "children": [10] }
  ]
}
```

#### Example Response

```json
{
  "quote": {
    "id": "quote_xxx",
    "expires_at": "2025-01-15T12:15:00Z",
    "property": {
      "id": "clx123abc",
      "name": "Soneva Fushi"
    },
    "room": {
      "id": "room_456",
      "name": "Crusoe Villa with Pool"
    },
    "pricing": {
      "price_per_night": 1500,
      "nights": 6,
      "subtotal": 9000,
      "taxes_and_fees": 1350,
      "total": 10350,
      "currency": "USD",
      "non_included_taxes": [
        {
          "name": "city_tax",
          "amount": "25.00",
          "currency_code": "USD",
          "payable_at": "check_in",
          "note": "Paid directly at check-in"
        }
      ]
    },
    "cancellation": {
      "policy": "Free cancellation until February 22, 2025",
      "refundable": true,
      "deadline": "2025-02-22T14:00:00Z",
      "timezone": "UTC+0"
    },
    "prebook": {
      "required_before_payment": true,
      "status": "not_started"
    },
    "hotel_policies": {
      "extra_info": "A local tourist tax may be charged during the stay and paid at the hotel.",
      "structured": {
        "pets": [],
        "deposit": []
      }
    }
  },
  "quotes": [
    {
      "id": "quote_xxx",
      "room": { "id": "room_456", "name": "Crusoe Villa with Pool" },
      "pricing": { "total": 10350, "currency": "USD" }
    }
  ]
}
```

#### cURL Example

```bash
curl -X POST https://api.tellandgo.com/api/v1/agent/quote \
  -H "X-API-Key: tg_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "property_id": "clx123abc",
    "room_id": "room_456",
    "check_in": "2025-03-01",
    "check_out": "2025-03-07",
    "residency": "US",
    "rooms": [
      { "adults": 1, "children": [0, 17] },
      { "adults": 1, "children": [10] }
    ]
  }'
```

For multi-room bookings, create the quote with `rooms` and then book using the selected `quote_id`. The API derives aggregate occupancy internally and stores the room allocation, so `/book` only needs the lead guest details; booking completion uses the same per-room split that was quoted.

---

### Prebook Quote

Verify or lock a selected quote before payment.

**Endpoint:** `POST /prebook`

**Version:** V2

#### Request Body

| Field      | Type   | Required | Description          |
| ---------- | ------ | -------- | -------------------- |
| `quote_id` | string | Yes      | Quote ID from /quote |

#### Example Request

```json
{
  "quote_id": "quote_xxx"
}
```

#### Example Response

```json
{
  "success": true,
  "quote_id": "quote_xxx",
  "prebook": {
    "required_before_payment": true,
    "status": "locked",
    "expires_at": "2025-01-15T18:15:00Z",
    "price_changed": false
  },
  "pricing": {
    "total": 10350,
    "currency": "USD"
  }
}
```

Some live quotes require this step and return `status=locked` when verification succeeds. Quotes that do not require a prebook phase return `status=not_required`. If final verification reports a price increase or decrease, this endpoint returns HTTP 409 with structured `details.pricing` and `details.prebook.direction` so the user can confirm the updated price before payment.

#### cURL Example

```bash
curl -X POST https://api.tellandgo.com/api/v1/agent/prebook \
  -H "X-API-Key: tg_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "quote_id": "quote_xxx" }'
```

---

### Create Booking

Create a booking from a valid quote. Quotes that require prebook must be locked first; `/book` rejects unverified quotes before payment. Provide one valid adult lead guest per room. Do not send placeholder guests for children or unnamed occupants; the quote already stores the occupancy.

`stripe_checkout` is a hosted browser payment flow, not a headless server-to-server payment call. After `/book` returns `payment.url`, redirect the customer’s browser to Stripe Checkout. Tell&Go then confirms the booking server-side from Stripe’s webhook and supplier status checks. The payment return page is only a browser convenience. API consumers should retrieve final status with `GET /bookings/:id` and can optionally register partner webhooks to receive async status events such as `booking.confirmed` or `booking.failed`.

**Endpoint:** `POST /book`

**Version:** V2

#### Request Body

| Field                 | Type    | Required | Description                                                                                                                                       |
| --------------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `quote_id`            | string  | Yes      | Quote ID from /quote endpoint                                                                                                                     |
| `guests`              | array   | Yes      | One valid adult lead guest per booked room                                                                                                        |
| `guests[].first_name` | string  | Yes      | Guest first name                                                                                                                                  |
| `guests[].last_name`  | string  | Yes      | Guest last name                                                                                                                                   |
| `guests[].email`      | string  | No       | Guest email. Recommended for the primary guest.                                                                                                   |
| `guests[].phone`      | string  | No       | Guest phone number                                                                                                                                |
| `guests[].is_primary` | boolean | No       | Mark as primary guest                                                                                                                             |
| `guests[].is_child`   | boolean | No       | Optional; only set when providing accurate child details                                                                                          |
| `guests[].age`        | number  | No       | Required when `guests[].is_child=true`                                                                                                            |
| `special_requests`    | string  | No       | Special requests                                                                                                                                  |
| `payment_method`      | string  | No       | Defaults to `stripe_checkout`. `redirect` is deprecated.                                                                                          |
| `success_url`         | string  | No       | Optional HTTPS URL to return the payer to after Stripe-hosted checkout succeeds. `booking_id` and `session_id` are appended when missing.         |
| `cancel_url`          | string  | No       | Optional HTTPS URL to return the payer to if Stripe-hosted checkout is cancelled. `booking_id` and `payment=cancelled` are appended when missing. |

#### Example Request

```json
{
  "quote_id": "quote_xxx",
  "guests": [
    {
      "first_name": "John",
      "last_name": "Doe",
      "email": "john@example.com",
      "phone": "+1234567890",
      "is_primary": true
    }
  ],
  "special_requests": "Honeymoon celebration",
  "payment_method": "stripe_checkout",
  "success_url": "https://partner.example/bookings/complete",
  "cancel_url": "https://partner.example/bookings/cancelled"
}
```

#### Example Response

```json
{
  "booking": {
    "id": "booking_xxx",
    "status": "pending_payment",
    "reference": "TG-2025-ABCDE",
    "payment": {
      "method": "stripe_checkout",
      "url": "https://checkout.stripe.com/c/pay/cs_test_xxx",
      "session_id": "cs_test_xxx",
      "expires_at": "2025-01-15T12:30:00Z"
    }
  }
}
```

#### cURL Example

```bash
curl -X POST https://api.tellandgo.com/api/v1/agent/book \
  -H "X-API-Key: tg_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "quote_id": "quote_xxx",
    "guests": [{
      "first_name": "John",
      "last_name": "Doe",
      "email": "john@example.com",
      "is_primary": true
    }],
    "payment_method": "stripe_checkout"
  }'
```

#### Final Booking Status

`stripe_checkout` is a hosted browser payment flow, not a headless server-to-server payment call. After `/book` returns `booking.payment.url`, redirect the customer’s browser to Stripe Checkout.

When payment is complete, Stripe redirects the customer to Tell&Go’s default booking status page. That page may initially show “Payment received, confirming your booking” while Tell&Go finalizes the booking server-side from payment and supplier status callbacks. Payment success is not the same as final hotel confirmation.

For API integrations, treat `GET /bookings/:id` as the canonical final-status lookup. If an async partner callback has been configured with Tell&Go for your integration, Tell&Go can also send final status events such as `booking.confirmed` or `booking.failed`. Partners do not call Tell&Go’s inbound `/webhook` endpoints; those are reserved for payment and supplier callbacks into Tell&Go.

---

### List Bookings

List all bookings for the authenticated partner.

**Endpoint:** `GET /bookings`

#### Query Parameters

| Parameter | Type   | Required | Default | Description                                                        |
| --------- | ------ | -------- | ------- | ------------------------------------------------------------------ |
| `limit`   | number | No       | 20      | Items per page (max 100)                                           |
| `offset`  | number | No       | 0       | Pagination offset                                                  |
| `status`  | string | No       | -       | Filter by status: `pending`, `confirmed`, `cancelled`, `completed` |

#### cURL Example

```bash
curl "https://api.tellandgo.com/api/v1/agent/bookings?limit=20&offset=0&status=confirmed" \
  -H "X-API-Key: tg_live_your_api_key"
```

---

### Get Booking Details

Retrieve details for a specific booking.

**Endpoint:** `GET /bookings/:id`

#### Path Parameters

| Parameter | Type   | Required | Description |
| --------- | ------ | -------- | ----------- |
| `id`      | string | Yes      | Booking ID  |

#### cURL Example

```bash
curl https://api.tellandgo.com/api/v1/agent/bookings/booking_xxx \
  -H "X-API-Key: tg_live_your_api_key"
```

---

### Cancel Booking

Cancel a booking. Subject to cancellation policy.

**Endpoint:** `DELETE /bookings/:id`

#### Path Parameters

| Parameter | Type   | Required | Description |
| --------- | ------ | -------- | ----------- |
| `id`      | string | Yes      | Booking ID  |

#### Request Body

| Field    | Type   | Required | Description                  |
| -------- | ------ | -------- | ---------------------------- |
| `reason` | string | No       | Optional cancellation reason |

#### Example Response

```json
{
  "success": true,
  "booking": {
    "id": "booking_xxx",
    "status": "cancelled",
    "refund": {
      "amount": 10350,
      "currency": "USD",
      "status": "processing"
    }
  }
}
```

#### cURL Example

```bash
curl -X DELETE https://api.tellandgo.com/api/v1/agent/bookings/booking_xxx \
  -H "X-API-Key: tg_live_your_api_key"
```

---

## Error Handling

All errors follow a consistent format.

### Error Response Format

```json
{
  "error": "error_code",
  "message": "Human-readable error description"
}
```

### Error Codes

| Status | Code             | Description                             |
| ------ | ---------------- | --------------------------------------- |
| 400    | `bad_request`    | Invalid request parameters              |
| 401    | `unauthorized`   | Invalid or missing API key              |
| 403    | `forbidden`      | Insufficient permissions                |
| 404    | `not_found`      | Resource not found                      |
| 409    | `conflict`       | Resource conflict (e.g., quote expired) |
| 429    | `rate_limited`   | Rate limit exceeded                     |
| 500    | `internal_error` | Server error                            |

---

## Code Examples

### Python

```python
import requests

API_KEY = "tg_live_your_key"
BASE_URL = "https://api.tellandgo.com/api/v1/agent"

headers = {"X-API-Key": API_KEY}

# Search for properties
response = requests.post(
    f"{BASE_URL}/search",
    json={
        "query": "romantic honeymoon maldives",
        "residency": "US",
        "constraints": {
            "destination": "maldives",
            "dates": {"check_in": "2026-08-01", "check_out": "2026-08-07"},
            "guests": {"adults": 2, "children": []},
        },
    },
    headers=headers
)
results = response.json()

# Get property details
property_id = results["properties"][0]["id"]
details = requests.get(
    f"{BASE_URL}/properties/{property_id}",
    headers=headers
).json()

print(f"Found: {details['property']['name']}")
```

### JavaScript / Node.js

```javascript
const API_KEY = "tg_live_your_key";
const BASE_URL = "https://api.tellandgo.com/api/v1/agent";

async function searchProperties(query, residency) {
  const response = await fetch(`${BASE_URL}/search`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-API-Key": API_KEY,
    },
    body: JSON.stringify({
      query,
      residency,
      constraints: {
        destination: "maldives",
        dates: { check_in: "2026-08-01", check_out: "2026-08-07" },
        guests: { adults: 2, children: [] },
      },
    }),
  });
  return response.json();
}

// Usage
const results = await searchProperties("luxury maldives resort", "US");
console.log(results.properties);
```

### TypeScript

```typescript
interface SearchResponse {
  success: boolean;
  properties: Property[];
  pagination: { total: number; has_more: boolean };
}

interface Property {
  id: string;
  name: string;
  location: { country: string; area: string };
  rating: number;
  match: { score: number; explanation: string };
}

async function search(
  query: string,
  residency: string,
): Promise<SearchResponse> {
  const res = await fetch("https://api.tellandgo.com/api/v1/agent/search", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-API-Key": process.env.TELLANDGO_API_KEY!,
    },
    body: JSON.stringify({
      query,
      residency,
      constraints: {
        destination: "maldives",
        dates: { check_in: "2026-08-01", check_out: "2026-08-07" },
        guests: { adults: 2, children: [] },
      },
    }),
  });
  return res.json();
}
```

---

## Resources

- **OpenAPI Specification:** [/api/openapi.yaml](/api/openapi.yaml)
- **Postman Collection:** [/api/postman-collection.json](/api/postman-collection.json)
- **Developer Portal:** [/developers](/developers)
- **Support:** [/contact](/contact)

---

_Last updated: May 2026_
