API REST
En lecture seule, en JSON, ouverte aux appels depuis le navigateur. Les noms des champs sont stables : un changement incompatible passerait par une nouvelle version.
Adresse de base
https://www.deveras.app/api/v1Accès et clés
Tu n’as pas besoin de clé pour commencer. Avec une clé, la limite est plus haute et tu peux suivre ta consommation. Envoie-la dans l’en-tête Authorization: Bearer … ou dans x-api-key.
curl -H "Authorization: Bearer $API_KEY" \
"https://www.deveras.app/api/v1/listings?city=playa-del-carmen"Ta clé est secrète : utilise-la depuis ton serveur, jamais dans du code qui arrive dans le navigateur. Si elle fuit, révoque-la et crées-en une autre.
Limites et cache
- Sans clé : 60 requêtes par minute et par adresse IP.
- Avec une clé : 600 requêtes par minute et par clé.
- Au-delà, nous répondons
429avec l’en-têteRetry-After(secondes à attendre). Avec une clé, chaque réponse contientX-RateLimit-Limit,X-RateLimit-RemainingetX-RateLimit-Reset. - Les réponses peuvent être mises en cache 60 secondes (
Cache-Control). Les annonces changent peu : garde les réponses et économise des requêtes.
Forme des réponses
Toute réponse réussie contient data (le résultat) et attribution (la mention à afficher). Les listes ajoutent pagination, avec les liens vers la page précédente et la suivante, repris dans l’en-tête Link.
{
"data": [
{
"id": "k7m2x9p",
"url": "https://www.deveras.app/en/p/bright-two-bedroom-near-the-beach-k7m2x9p",
"title": "Bright two-bedroom near the beach",
"language": "en",
"type": "apartment",
"operation": "rent",
"terms": [
"long",
"mid"
],
"price": {
"amount": 1200,
"currency": "USD",
"amount_mxn": 21960,
"period": "month"
},
"sale": null,
"bedrooms": 2,
"bathrooms": 1.5,
"area_m2": 78,
"land_m2": null,
"furnished": true,
"pets_allowed": false,
"amenities": [
"pool",
"ac",
"wifi"
],
"location": {
"city": {
"slug": "playa-del-carmen",
"name": "Playa del Carmen"
},
"zone": {
"slug": "centro",
"name": "Centro"
},
"coordinates": {
"lat": 20.627,
"lng": -87.074,
"precision": "approximate"
}
},
"photos": [
{
"url": "https://www.deveras.app/media/public/listings/k7m2x9p/1.jpg",
"width": 1600,
"height": 1200,
"alt": "Living room",
"room": "living"
}
],
"advertiser": {
"handle": "ana-lopez",
"name": "Ana López",
"role": "owner",
"agency_name": null,
"avatar_url": null,
"trust_score": 82,
"reviews": {
"count": 4,
"average": 4.75
},
"verifications": [
{
"kind": "email",
"verified_at": "2026-01-05T10:00:00.000Z"
},
{
"kind": "identity",
"verified_at": "2026-03-02T10:00:00.000Z"
}
],
"url": "https://www.deveras.app/en/u/ana-lopez"
},
"verifications": [
{
"kind": "ownership",
"verified_at": "2026-04-01T10:00:00.000Z"
}
],
"shares_commission": false,
"demo": false,
"published_at": "2026-06-10T15:00:00.000Z",
"availability_confirmed_at": "2026-10-01T12:00:00.000Z"
}
],
"pagination": {
"page": 1,
"per_page": 24,
"total": 1,
"pages": 1,
"links": {
"self": "https://www.deveras.app/api/v1/listings?city=playa-del-carmen&beds=2&max=25000",
"first": "https://www.deveras.app/api/v1/listings?city=playa-del-carmen&beds=2&max=25000",
"last": "https://www.deveras.app/api/v1/listings?city=playa-del-carmen&beds=2&max=25000",
"prev": null,
"next": null
}
},
"attribution": {
"text": "Listings from Deveras",
"url": "https://www.deveras.app/en",
"license_url": "https://www.deveras.app/en/developers/license",
"notice": "Free to reuse, including commercially, as long as you show this mention visibly and link each listing to its `url`. Do not remove verification context or the demo flag, and do not publish contact details."
}
}Bon à savoir sur les champs
- url
- La page de l’annonce sur Deveras. C’est le lien obligatoire dans toute réutilisation.
- price
amountest dans la devise de l’annonce (currency) ;amount_mxnest le même prix en pesos. Les filtresminetmaxet le tri par prix utilisent les pesos.- sale
- Ventes seulement (
operation: sale,price.period: total) : vente sur plan, livraison, type de titre, charges et prix au m².nullpour une location. - location.coordinates
precisionvautexactouapproximate. Si la position est approximative, le point est décalé exprès : dessine une zone, pas une épingle. Peut valoirnull.- verifications
- Les preuves contrôlées par la plateforme, avec leur type et leur date. Sur l’annonce, elles concernent le bien ; sous
advertiser, la personne. Une liste vide veut dire « non vérifié ». - demo
truepour les données de démonstration, qui ne sont pas de vraies annonces. Elles sont absentes sauf si tu demandesdemo=1.- locale
locale=es,enoufrchoisit la langue des titres, des descriptions et des liens. Sans traduction, tu reçois le texte d’origine (languagete dit lequel).
Ce que nous ne renvoyons jamais
Adresse exacte, téléphone, WhatsApp, e-mail, pièces d’identité, identifiants internes et annonces non publiées. Les profils de locataires non plus. Si un texte libre contient un numéro de téléphone ou un e-mail, nous le masquons.
Routes
Chercher des annonces
GET/api/v1/listings
Les annonces publiées, de la plus récente à la plus ancienne, avec les mêmes filtres que la recherche du site. Locations par défaut ; ventes avec operation=sale.
- operationstring — optionnel — rent · sale — par défaut : rent
rent(par défaut) ousale. Une recherche renvoie l’une ou l’autre, jamais les deux.- citystring — optionnel
- Ville (identifiant de
/places). Sans elle, la recherche porte sur toutes les villes. - zonestring — optionnel
- Quartier dans la ville. Nécessite
city. - typestring — optionnel — apartment · house · studio · room · villa · commercial · land
- Type de bien.
- bedsinteger — optionnel
- Nombre minimum de chambres.
- bathsinteger — optionnel
- Nombre minimum de salles de bain.
- mininteger — optionnel
- Prix minimum en pesos (MXN) : le loyer, ou le prix total d’une vente.
- maxinteger — optionnel
- Prix maximum en pesos (MXN) : le loyer, ou le prix total d’une vente.
- furnishedboolean — optionnel
1pour ne voir que les meublés.- petsboolean — optionnel
1pour ne voir que les annonces qui acceptent les animaux. Locations seulement.- termstring — optionnel — long · mid · short
- Durée :
long(12 mois ou plus),mid(1 à 11 mois) oushort(à la nuit ou à la semaine). Locations seulement. - amenitiesstring[] — optionnel — pool · gym · ac · parking · rooftop · security · washer · elevator · cowork · balcony · garden · kitchen · wifi · tv · beach_walk · generator · cistern · storage · bbq · jacuzzi
- Équipements que l’annonce doit tous avoir, séparés par des virgules.
- verifiedboolean — optionnel
1pour ne voir que les annonceurs dont l’identité est vérifiée.- qstring — optionnel
- Texte libre, cherché dans le titre et la description.
- advertiserstring — optionnel
- Seulement les annonces de ce profil.
- sortstring — optionnel — recent · price_asc · price_desc — par défaut : recent
- Tri :
recent,price_ascouprice_desc. - pageinteger — optionnel — par défaut : 1
- Numéro de page, à partir de 1.
- per_pageinteger — optionnel — par défaut : 24
- Annonces par page.
- demoboolean — optionnel — par défaut : 0
1pour inclure les données de démonstration (marquéesdemo: true).- localestring — optionnel — es · en · fr — par défaut : es
- Langue des textes et des liens :
es,enoufr.
curl "https://www.deveras.app/api/v1/listings?city=playa-del-carmen&beds=2&max=25000&furnished=1"const response = await fetch("https://www.deveras.app/api/v1/listings?city=playa-del-carmen&beds=2&max=25000");
const { data, pagination, attribution } = await response.json();
for (const listing of data) {
// listing.url is the page of the listing: always link to it.
console.log(listing.title, listing.price.amount, listing.price.currency, listing.url);
}
// Show attribution.text, linked to attribution.url, wherever you display the listings.
console.log(attribution.text, attribution.url, pagination.total);Lire une annonce
GET/api/v1/listings/{shortId}
L’annonce complète : description, toutes les photos, conditions, charges comprises, distances et vérifications.
- shortIdstring
- Identifiant de l’annonce (champ
id). - demoboolean — optionnel — par défaut : 0
1pour inclure les données de démonstration (marquéesdemo: true).- localestring — optionnel — es · en · fr — par défaut : es
- Langue des textes et des liens :
es,enoufr.
curl "https://www.deveras.app/api/v1/listings/k7m2x9p?locale=en"Villes et quartiers
GET/api/v1/places
Les villes et leurs quartiers, avec les identifiants attendus par les filtres city et zone et le nombre d’annonces en location (listing_count) et en vente (sale_count).
- demoboolean — optionnel — par défaut : 0
1pour inclure les données de démonstration (marquéesdemo: true).- localestring — optionnel — es · en · fr — par défaut : es
- Langue des textes et des liens :
es,enoufr.
curl "https://www.deveras.app/api/v1/places"Profil public d’un annonceur
GET/api/v1/profiles/{handle}
Nom, rôle, score de confiance, avis et preuves vérifiées d’un propriétaire ou d’un agent.
- handlestring
- Identifiant du profil (champ
advertiser.handle). - demoboolean — optionnel — par défaut : 0
1pour inclure les données de démonstration (marquéesdemo: true).- localestring — optionnel — es · en · fr — par défaut : es
- Langue des textes et des liens :
es,enoufr.
curl "https://www.deveras.app/api/v1/profiles/ana-lopez"Erreurs
Les erreurs utilisent le code HTTP habituel et toujours la même forme. Appuie-toi sur code, qui est stable ; message est là pour toi.
{
"error": {
"code": "invalid_parameter",
"message": "One or more parameters are invalid.",
"status": 400,
"details": [
{
"param": "beds",
"message": "Invalid input: expected number, received string"
}
],
"docs_url": "https://www.deveras.app/en/developers/api"
}
}- invalid_parameterHTTP 400
- Un paramètre manque, est inconnu ou a une valeur invalide.
detailsdit lequel. - invalid_api_keyHTTP 401
- La clé n’existe pas, est révoquée ou est mal écrite.
- not_foundHTTP 404
- La route n’existe pas.
- listing_not_foundHTTP 404
- Aucune annonce publiée n’a cet identifiant.
- profile_not_foundHTTP 404
- Aucun profil public d’annonceur n’a cet identifiant.
- place_not_foundHTTP 404
- La ville ou le quartier n’existe pas. Consulte
/places. - advertiser_not_foundHTTP 404
- Le profil indiqué dans
advertisern’existe pas. - method_not_allowedHTTP 405
- L’API est en lecture seule : utilise
GET. - rate_limitedHTTP 429
- Trop de requêtes. Attends la durée indiquée par
Retry-After. - internal_errorHTTP 500
- Quelque chose a échoué de notre côté. Réessaie.
Document OpenAPI
La description complète de l’API au format OpenAPI 3.1 est produite à partir des définitions qu’utilise le serveur : elle est toujours à jour. Sers-t’en pour générer un client ou l’importer dans ton outil préféré.