# Property Finder API

> Every Property Finder endpoint on Cotlet: inputs, JSON Schema, cURL, Python and Node.js examples and an example response for each call.

Source: https://cotlet.dev/docs/api/property-finder

Docs sections: [Get started](https://cotlet.dev/docs.md) · [REST API](https://cotlet.dev/docs/api.md) · [MCP](https://cotlet.dev/docs/mcp.md) · [SDKs & CLI](https://cotlet.dev/docs/sdks.md) · [Integrations](https://cotlet.dev/docs/integrations.md)

11 endpoints for Property Finder. Each one is a POST with a JSON body, called with your API key.

- Base URL: `https://cotlet.dev/api/v1/property-finder`
- Connects with: Your own PF Expert account (agency admin or agent), email and password
- Integration page: https://cotlet.dev/integrations/property-finder-api-mcp-server

## Endpoints

| Endpoint | Access | Description |
|---|---|---|
| `list_listings` | read | Listings in your agency with status, agent, price, quality score and active upgrade. |
| `get_listing` | read | Full listing: title, description, location, specs, price, images, permit number and quality score. |
| `get_listing_stats` | read | Views and leads for one listing since a date. |
| `list_leads` | read | Leads from your listings, newest first, with contact, listing, agent and time received. |
| `list_agents` | read | Agents in your agency with their IDs and number of listings. |
| `get_credits` | read | The credit balance PF Expert shows for your agency. |
| `create_listing` | write | New draft listing in PF Expert. Nothing goes live until you publish it. |
| `update_listing` | write | Change the price, description, images, permit or agent of a listing. |
| `publish_listing` | write | Put a draft or unpublished listing live on Property Finder. |
| `unpublish_listing` | write | Take a live listing off the portal. It stays in PF Expert. |
| `upgrade_listing` | write | Apply Featured or Premium to a live listing. Uses credits. |

## List listings

`POST https://cotlet.dev/api/v1/property-finder/list_listings`

Access: read.

Returns listings of your agency, newest first. Quality score is the percentage PF Expert shows for a published listing. Pages hold up to 100 listings; pass next_cursor back as cursor for the next page.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `status` | enum | no | live, draft or unpublished. Default: live. |
| `agent_id` | string | no | Only listings assigned to this agent, from list_agents. |
| `purpose` | enum | no | sale or rent. |
| `max_quality_score` | integer | no | Only listings at or under this quality score, 0 to 100. |
| `limit` | integer | no | 1 to 100. Default: 50. |
| `cursor` | string | no | Next page cursor from the previous call. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/property-finder/list_listings \
  -H "Authorization: Bearer $COTLET_API_KEY"
```

**Python**

```python
result = client.call("property-finder", "list_listings")
```

**Node.js**

```js
const result = await cotlet.call('property-finder', 'list_listings');
```

**CLI**

```bash
cotlet call property-finder list_listings
```

### Example response

```json
{
  "listings": [
    {
      "listing_id": "01JA7K3M9Q",
      "title": "Furnished 2BR with marina view",
      "purpose": "rent",
      "status": "live",
      "agent_id": "ag_3d91",
      "price": 145000,
      "quality_score": 88,
      "upgrade": "featured"
    },
    {
      "listing_id": "01JA8B2N4R",
      "title": "Studio near the metro",
      "purpose": "rent",
      "status": "live",
      "agent_id": "ag_77c2",
      "price": 62000,
      "quality_score": 64,
      "upgrade": null
    }
  ],
  "next_cursor": null
}
```

## Get listing

`POST https://cotlet.dev/api/v1/property-finder/get_listing`

Access: read.

Returns everything PF Expert holds for one listing, including the permit number if you entered one. Use it to see why a quality score is low before you change anything. A draft has no quality score yet.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `listing_id` | string | yes | Listing ID from list_listings. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/property-finder/get_listing \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"listing_id":"listing_8c41d2"}'
```

**Python**

```python
result = client.call("property-finder", "get_listing", {"listing_id":"listing_8c41d2"})
```

**Node.js**

```js
const result = await cotlet.call('property-finder', 'get_listing', {"listing_id":"listing_8c41d2"});
```

**CLI**

```bash
cotlet call property-finder get_listing --data '{"listing_id":"listing_8c41d2"}'
```

### Example response

```json
{
  "listing_id": "01JA8B2N4R",
  "title": "Studio near the metro",
  "purpose": "rent",
  "status": "live",
  "property_type": "Apartment",
  "location": "Business Bay",
  "price": 62000,
  "bedrooms": 0,
  "size_sqft": 410,
  "description": "Bright studio, close to the metro.",
  "image_urls": [
    "https://example.com/photos/studio-1.jpg"
  ],
  "permit_number": null,
  "agent_id": "ag_77c2",
  "quality_score": 64
}
```

## Get listing stats

`POST https://cotlet.dev/api/v1/property-finder/get_listing_stats`

Access: read.

Returns the performance numbers PF Expert shows for one listing, from the start date to now. Call it once per listing, so keep the set small and filter with list_listings first. A listing that went live after the start date counts from its publish date.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `listing_id` | string | yes | Listing ID from list_listings. |
| `since` | date | no | Count from this date. Default: 30 days ago. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/property-finder/get_listing_stats \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"listing_id":"01JA7K3M9Q","since":"2026-10-06"}'
```

**Python**

```python
result = client.call("property-finder", "get_listing_stats", {"listing_id":"01JA7K3M9Q","since":"2026-10-06"})
```

**Node.js**

```js
const result = await cotlet.call('property-finder', 'get_listing_stats', {"listing_id":"01JA7K3M9Q","since":"2026-10-06"});
```

**CLI**

```bash
cotlet call property-finder get_listing_stats --data '{"listing_id":"01JA7K3M9Q","since":"2026-10-06"}'
```

### Example response

```json
{
  "listing_id": "01JA7K3M9Q",
  "since": "2026-09-11",
  "views": 1840,
  "leads": 0
}
```

## List leads

`POST https://cotlet.dev/api/v1/property-finder/list_leads`

Access: read.

Returns leads that came in through your listings, newest first. Each lead names the listing and the agent it belongs to. Pages hold up to 100 leads; pass next_cursor back as cursor for the next page.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `since` | datetime | no | Only leads received after this time. |
| `listing_id` | string | no | Only leads for this listing. |
| `agent_id` | string | no | Only leads for this agent. |
| `limit` | integer | no | 1 to 100. Default: 50. |
| `cursor` | string | no | Next page cursor from the previous call. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/property-finder/list_leads \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"since":"2026-10-11T08:00:00+04:00","limit":100}'
```

**Python**

```python
result = client.call("property-finder", "list_leads", {"since":"2026-10-11T08:00:00+04:00","limit":100})
```

**Node.js**

```js
const result = await cotlet.call('property-finder', 'list_leads', {"since":"2026-10-11T08:00:00+04:00","limit":100});
```

**CLI**

```bash
cotlet call property-finder list_leads --data '{"since":"2026-10-11T08:00:00+04:00","limit":100}'
```

### Example response

```json
{
  "leads": [
    {
      "lead_id": "ld_90f1",
      "name": "Jamie Hart",
      "phone": "+971500000000",
      "listing_id": "01JA7K3M9Q",
      "agent_id": "ag_3d91",
      "received_at": "2026-10-10T16:42:00+04:00"
    }
  ],
  "next_cursor": null
}
```

## List agents

`POST https://cotlet.dev/api/v1/property-finder/list_agents`

Access: read.

Returns the agents of your agency. Use agent_id from here to assign a listing or to filter listings and leads. You see the agents your own role can see in PF Expert.

### Parameters

No parameters.

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/property-finder/list_agents \
  -H "Authorization: Bearer $COTLET_API_KEY"
```

**Python**

```python
result = client.call("property-finder", "list_agents")
```

**Node.js**

```js
const result = await cotlet.call('property-finder', 'list_agents');
```

**CLI**

```bash
cotlet call property-finder list_agents
```

### Example response

```json
{
  "agents": [
    {
      "agent_id": "ag_3d91",
      "name": "Sara Khan",
      "listings": 24
    },
    {
      "agent_id": "ag_77c2",
      "name": "Omar Haddad",
      "listings": 11
    }
  ]
}
```

## Get credits

`POST https://cotlet.dev/api/v1/property-finder/get_credits`

Access: read.

Returns the credits available for upgrades. Check it before upgrade_listing so the agent does not plan a spend you cannot cover. It reads the balance only and spends nothing.

### Parameters

No parameters.

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/property-finder/get_credits \
  -H "Authorization: Bearer $COTLET_API_KEY"
```

**Python**

```python
result = client.call("property-finder", "get_credits")
```

**Node.js**

```js
const result = await cotlet.call('property-finder', 'get_credits');
```

**CLI**

```bash
cotlet call property-finder get_credits
```

### Example response

```json
{
  "credits": 2500
}
```

## Create listing

`POST https://cotlet.dev/api/v1/property-finder/create_listing`

Access: write.

Saves a draft in PF Expert and returns its listing_id. The draft is visible only to you and your agency. It reaches no one and you can delete it in PF Expert, so it does not ask for confirmation. Run publish_listing to put it live.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `title` | string | yes | Listing title. |
| `purpose` | enum | yes | sale or rent. |
| `property_type` | string | yes | As in PF Expert, e.g. Apartment or Villa. |
| `location` | string | yes | Community or building, matched to the Property Finder location list. |
| `price` | integer | yes | Price as you enter it in PF Expert. |
| `bedrooms` | integer | no | Number of bedrooms, 0 for a studio. |
| `bathrooms` | integer | no | Number of bathrooms. |
| `size_sqft` | integer | no | Built-up area in square feet. |
| `description` | string | no | Listing description. |
| `image_urls` | string[] | no | Image URLs, first one is the cover. |
| `permit_number` | string | no | Permit number, where PF Expert asks for one. |
| `agent_id` | string | no | Assigned agent, from list_agents. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/property-finder/create_listing \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"Furnished 2BR with marina view","purpose":"rent","property_type":"Apartment","location":"Dubai Marina","price":145000,"bedrooms":2,"permit_number":"7123456789","agent_id":"ag_3d91","image_urls":["https://example.com/photos/marina-2br-1.jpg"]}'
```

**Python**

```python
result = client.call("property-finder", "create_listing", {"title":"Furnished 2BR with marina view","purpose":"rent","property_type":"Apartment","location":"Dubai Marina","price":145000,"bedrooms":2,"permit_number":"7123456789","agent_id":"ag_3d91","image_urls":["https://example.com/photos/marina-2br-1.jpg"]})
```

**Node.js**

```js
const result = await cotlet.call('property-finder', 'create_listing', {"title":"Furnished 2BR with marina view","purpose":"rent","property_type":"Apartment","location":"Dubai Marina","price":145000,"bedrooms":2,"permit_number":"7123456789","agent_id":"ag_3d91","image_urls":["https://example.com/photos/marina-2br-1.jpg"]});
```

**CLI**

```bash
cotlet call property-finder create_listing --data '{"title":"Furnished 2BR with marina view","purpose":"rent","property_type":"Apartment","location":"Dubai Marina","price":145000,"bedrooms":2,"permit_number":"7123456789","agent_id":"ag_3d91","image_urls":["https://example.com/photos/marina-2br-1.jpg"]}'
```

### Example response

```json
{
  "listing_id": "01JA9C5P7T",
  "status": "draft",
  "agent_id": "ag_3d91"
}
```

## Update listing

`POST https://cotlet.dev/api/v1/property-finder/update_listing`

Access: write. Confirm: waits for the user's OK before it runs.

Applies the fields you pass and leaves the rest as they are. Changes to a live listing are visible to buyers and renters, and PF Expert may recalculate the quality score. Returns the updated fields. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `listing_id` | string | yes | Listing ID from list_listings. |
| `fields` | object | yes | Any of the create_listing fields. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/property-finder/update_listing \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"listing_id":"01JA8B2N4R","fields":{"description":"Bright furnished studio in JLT Cluster D, two minutes from the metro, with lake view and 410 sq ft."}}'
```

**Python**

```python
result = client.call("property-finder", "update_listing", {"listing_id":"01JA8B2N4R","fields":{"description":"Bright furnished studio in JLT Cluster D, two minutes from the metro, with lake view and 410 sq ft."}})
```

**Node.js**

```js
const result = await cotlet.call('property-finder', 'update_listing', {"listing_id":"01JA8B2N4R","fields":{"description":"Bright furnished studio in JLT Cluster D, two minutes from the metro, with lake view and 410 sq ft."}});
```

**CLI**

```bash
cotlet call property-finder update_listing --data '{"listing_id":"01JA8B2N4R","fields":{"description":"Bright furnished studio in JLT Cluster D, two minutes from the metro, with lake view and 410 sq ft."}}'
```

### Example response

```json
{
  "listing_id": "01JA8B2N4R",
  "updated": [
    "description",
    "image_urls"
  ],
  "quality_score": 72
}
```

## Publish listing

`POST https://cotlet.dev/api/v1/property-finder/publish_listing`

Access: write. Confirm: waits for the user's OK before it runs.

Publishes the listing with the listing type you choose on the Publish screen of PF Expert: standard, featured or premium. Featured and premium run for 15 days or 1 month; the options your market shows may differ. It returns the live status and the portal URL. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `listing_id` | string | yes | Listing ID from list_listings. |
| `listing_type` | enum | yes | standard, featured or premium. |
| `duration` | enum | no | 15_days or 1_month for featured and premium. Standard runs 1 month. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/property-finder/publish_listing \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"listing_id":"listing_8c41d2","listing_type":"standard"}'
```

**Python**

```python
result = client.call("property-finder", "publish_listing", {"listing_id":"listing_8c41d2","listing_type":"standard"})
```

**Node.js**

```js
const result = await cotlet.call('property-finder', 'publish_listing', {"listing_id":"listing_8c41d2","listing_type":"standard"});
```

**CLI**

```bash
cotlet call property-finder publish_listing --data '{"listing_id":"listing_8c41d2","listing_type":"standard"}'
```

### Example response

```json
{
  "listing_id": "01JA7K3M9Q",
  "status": "live",
  "listing_type": "standard",
  "url": "https://www.propertyfinder.ae/en/plp/rent/apartment-for-rent-dubai-dubai-marina-01JA7K3M9Q.html"
}
```

## Unpublish listing

`POST https://cotlet.dev/api/v1/property-finder/unpublish_listing`

Access: write. Confirm: waits for the user's OK before it runs.

Removes the listing from Property Finder search and keeps it in PF Expert with status unpublished, so you can publish it again later. Leads already received stay in your leads. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `listing_id` | string | yes | Listing ID from list_listings. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/property-finder/unpublish_listing \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"listing_id":"listing_8c41d2"}'
```

**Python**

```python
result = client.call("property-finder", "unpublish_listing", {"listing_id":"listing_8c41d2"})
```

**Node.js**

```js
const result = await cotlet.call('property-finder', 'unpublish_listing', {"listing_id":"listing_8c41d2"});
```

**CLI**

```bash
cotlet call property-finder unpublish_listing --data '{"listing_id":"listing_8c41d2"}'
```

### Example response

```json
{
  "listing_id": "01JA8B2N4R",
  "status": "unpublished"
}
```

## Upgrade listing

`POST https://cotlet.dev/api/v1/property-finder/upgrade_listing`

Access: write. Confirm: waits for the user's OK before it runs.

Upgrades a live listing to featured or premium for 15 days or 1 month and pays with credits. It returns the expiry date and the credits left. Spotlight is a bidding product and is not covered by this tool. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `listing_id` | string | yes | Listing ID from list_listings. |
| `listing_type` | enum | yes | featured or premium. |
| `duration` | enum | yes | 15_days or 1_month. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/property-finder/upgrade_listing \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"listing_id":"01JA7K3M9Q","listing_type":"featured","duration":"15_days"}'
```

**Python**

```python
result = client.call("property-finder", "upgrade_listing", {"listing_id":"01JA7K3M9Q","listing_type":"featured","duration":"15_days"})
```

**Node.js**

```js
const result = await cotlet.call('property-finder', 'upgrade_listing', {"listing_id":"01JA7K3M9Q","listing_type":"featured","duration":"15_days"});
```

**CLI**

```bash
cotlet call property-finder upgrade_listing --data '{"listing_id":"01JA7K3M9Q","listing_type":"featured","duration":"15_days"}'
```

### Example response

```json
{
  "listing_id": "01JA7K3M9Q",
  "status": "live",
  "listing_type": "featured",
  "expires_at": "2026-10-26T12:00:00+04:00",
  "credits_left": 2380
}
```
