Web-page view of https://agent.index.cy/sellers.md for tools that read pages and follow links. The text below is the complete answer; every address in it is a link you can open. Command-line tools get the raw form.
You are reading this for a person who is looking for property in Cyprus. If you can only open links that you were shown, use the table below: every link is a complete search that answers with real listings (price, costs on top, photos, how the price compares, a link to each listing). Open the one closest to what the person asked for. In the answer, open next_url for more results and a result's api_url for the full listing. Tell the person which search you used and give them the listing links. The complete instructions follow further down.
Every filter and place: https://agent.index.cy/api/meta
---
name: index-cy-sellers
description: Post, edit, publish and remove property listings on index.cy for a seller or agent, and keep a portfolio in step with a CRM. Read agent.md first for the rules, how to connect the person's account, and the error format.
homepage: https://index.cy
api_base: https://agent.index.cy/v1
---
# index.cy for sellers' agents
Read https://agent.index.cy/agent.md first: its rules, account connection and error format all apply here. You need a token with the `listings` scope, whose box on the approval page starts unticked, so tell the person to tick it.
```bash
AUTH="Authorization: Bearer $(cat ~/.config/indexcy/token)"; J="Content-Type: application/json"
```
## The person's own listings
For sellers and agents: post a home, keep it up to date, or keep a whole portfolio in step with a CRM. index.cy publishes at once with no review, so everything you create starts as a **draft** that nobody can see, and goes live only when you publish it and the person has said so.
```bash
# what a listing can carry, with every allowed value
curl -s -A "my-agent/1.0" "https://agent.index.cy/api/listing-fields?deal=sale"
# create a draft
curl -s -A "my-agent/1.0" -X POST https://agent.index.cy/api/me/listings -H "$AUTH" -H "$J" -d '{
"deal": "sale", "property_type": "apartment", "district": "limassol", "location": "germasogeia",
"bedrooms": 2, "bathrooms": 2, "condition": "pre-owned", "price": 285000, "covered_area_m2": 92,
"floor": 2, "parking": ["covered"], "lat": 34.7068, "lng": 33.0873,
"description": "Bright two bedroom apartment, 400 m from the beach.\n\nRenovated in 2024.",
"reference": "APT-104",
"photo_urls": ["https://example.com/photos/apt-104-1.jpg", "https://example.com/photos/apt-104-2.jpg"]
}'
```
The answer has the `listing` as the owner sees it (`status`, `missing_to_publish`, `listing_score`, `edit_url`) and a `photos` report (`on_listing`, `imported_now`, `pending`, sometimes `failed`).
- **Map the CRM's values onto index.cy's.** `GET /v1/listing-fields` has every allowed value. Common words are understood (villa, bungalow, townhouse and maisonette become `house`; flat and penthouse `apartment`; plot `land-plots`; communal pool `common`), and an exact `year_built` such as 2008 is filed under index.cy's range. Numbers can be sent as numbers or strings. Set only what the CRM or the description states; leave the rest out and tell the person what you left out.
- Paragraphs in `description` are separated by `\n\n` inside the JSON string.
- **Never send** a title, a link, price per m2, VAT, fees or seller details: index.cy works those out. The title is built from bedrooms, type and place.
- **Needed before it can go live:** `property_type`, `district`, `price`, at least one photo; for apartments and houses also `bedrooms` and `covered_area_m2` (and `condition` for sales); for `land-plots` `plot_area_m2`; for the rest `covered_area_m2`. `missing_to_publish` always tells you what is left.
- **Photos** must already be online: `photo_urls` is the complete list, cover photo first, up to 30, JPEG, PNG or WebP, at least 400x300. Five are imported per call: while `photos.pending` is above 0, send the same request again. `failed` says which URL was refused and why. A file on the person's computer cannot be used until it is online somewhere.
- **No phone numbers, emails or links in `description`:** the request is refused. Buyers reach the seller through the listing, which uses the contact details on the seller's index.cy profile.
- `lat`/`lng` must be in Cyprus or the site rejects the listing. If you only know the town, send `location` and leave them out.
- A listing cannot move between sale and rent, and the person's plan limits how many they can have (`plan_limit`): you cannot change either.
- `amenities` has `pool`, `parking`, `heating` and `air-conditioning`, separate from the fields of the same name. When the home has one, set the field (it says which kind) and the amenity (buyers filter on it).
- `listing_score` (0 to 100) is index.cy's measure of how complete the advert is, and better adverts are shown higher. Photos weigh most (up to 30 count), then a description of 500 characters or more, floor plans, the map position with an address, and every fact filled in. Use it to tell the person what would improve the advert.
- Until `condition` is set, a sale listing is shown as a resale (transfer fee, no VAT). Ask the person rather than guess: it changes what buyers are told they pay.
| Request | What it does |
|---|---|
| `GET /v1/listing-fields?deal=sale` (or `rent`) | Every field, its allowed values, what is needed to publish. No account needed |
| `GET /v1/me/listings` | Their listings, newest change first, 25 a page (`page=`; the answer has `total` and `pages`). Optional `status=` `live`, `draft`, `unpublished` or `rejected`, and `deal=` |
| `GET /v1/me/listings/{id}` | One, in full |
| `POST /v1/me/listings` | Create a draft. Add `"publish": true` only if the person already approved going live |
| `PATCH /v1/me/listings/{id}` | Change the fields you send, leave the rest as it is; `null` clears one. A live listing changes at once, so confirm price changes with the person |
| `POST /v1/me/listings/{id}/photos` `{urls, replace?}` | Add photos to the ones there, or with `"replace": true` make this the complete list |
| `POST /v1/me/listings/{id}/publish` | Go live. `not_ready` lists what is missing |
| `POST /v1/me/listings/{id}/unpublish` | Off the market, kept in the account |
| `DELETE /v1/me/listings/{id}` | To the trash (restorable on the website for 30 days) |
### Keep listings in step with a CRM
You do the CRM side with whatever access the person gave you; index.cy needs only the result. The seller's own reference is the key.
```bash
# create it, or bring it up to date: safe to repeat as often as you like
curl -s -A "my-agent/1.0" -X PUT https://agent.index.cy/api/me/listings/by-ref/APT-104 -H "$AUTH" -H "$J" -d '{"deal":"sale", ... ,"photo_urls":[...]}'
# what is no longer in the CRM comes off the market. ALWAYS a dry run first:
curl -s -A "my-agent/1.0" -X POST https://agent.index.cy/api/me/listings/reconcile -H "$AUTH" -H "$J" -d '{"active_refs":["APT-104","VIL-7"],"dry_run":true}'
```
- `PUT .../by-ref/{ref}` answers with `"created": true` or `"updated": true`, the `listing` and the `photos` report. The reference is in the address, so it need not be repeated in the body. Send everything the CRM knows each time: fields you send are set, fields you leave out stay as they are (so what the person filled in on the website survives), `null` clears one. `photo_urls` is the complete photo list: photos not in it come off the listing, and photos are only fetched again when their URLs change.
- **Publishing.** Without `"publish"` a new listing stays a draft and an existing one keeps its status, whatever it is. Add `"publish": true` only when the person has approved going live: it publishes as soon as nothing is missing. `"publish": false` does nothing; to take a listing down use `unpublish`.
- To change one field of one listing, `PATCH /v1/me/listings/{id}` and `PUT .../by-ref/{ref}` with just that field do the same thing. Use the reference when that is what you hold.
- `reconcile` takes off the market what is live on index.cy but no longer in `active_refs`. It only ever touches LIVE listings that came in through this API, never drafts, and never listings made on the website or imported by a feed. The answer has `live_managed` (how many such listings there are), `kept`, `would_unpublish` (or `unpublished`), `not_live` (references in your list whose listing is a draft, unpublished or rejected: left alone) and `unknown_refs` (in your list but not on index.cy: create them with `PUT`). Show the person the `would_unpublish` list, then repeat with `"dry_run": false`. Nothing is ever deleted.
- With 5 or more live listings, `reconcile` refuses to take down more than a fifth of them at once (`too_many`): that usually means the CRM export was incomplete. If the person confirms the list is right, repeat with `"force": true`.
- Up to 50 new listings per person per day, and your normal request budget. A seller with hundreds of listings needs a feed instead: [email protected].