Guides de démarrage, références d'API et tutoriels pour intégrer la cartographie, le géocodage et le routage TMaps.
Bienvenue dans la documentation TMaps. Cette section couvre tout ce dont vous avez besoin pour intégrer nos services : créer un compte, gérer vos clés API, sécuriser vos appels par domaine et utiliser chaque endpoint avec des exemples de code copiables.
Si c'est votre première intégration, suivez le démarrage rapide. Si vous cherchez la référence d'un endpoint précis, utilisez la barre latérale.
Créez votre compte, générez une clé API, autorisez vos domaines et lancez votre première requête en moins de 5 minutes.
→Comment passer votre clé API, comment fonctionnent les domaines autorisés et comment appeler l'API depuis un serveur.
→Tuiles PNG prêtes à brancher dans Leaflet, MapLibre ou OpenLayers. Couverture mondiale optimisée pour la Tunisie.
→Quatre styles vectoriels (streets, dark, terrain, sunny) consommables avec MapLibre GL pour des cartes ultra-rapides.
→Convertissez une adresse libre en coordonnées GPS précises, avec un score de confiance et la décomposition (commune, délégation, gouvernorat).
→Calculez un itinéraire optimal entre deux points ou plus, avec turn-by-turn, distance et durée.
→Créez, désactivez ou révoquez vos clés API depuis la console TMaps.
→Liste complète des codes HTTP et de leur signification (400, 401, 403, 404, 429, 5xx).
→api_key en query string.lat = latitude (–90 à 90), lng = longitude (–180 à 180), en degrés décimaux WGS84.403.Créez votre compte, générez une clé API, autorisez vos domaines et lancez votre première requête en moins de 5 minutes.
Cette page résume les trois étapes pour passer de zéro à votre premier appel API. Chaque étape est détaillée dans sa propre page : suivez les liens pour aller en profondeur.
Rendez-vous sur app.tmaps.tn et créez un compte avec votre email + mot de passe ou en un clic via Google.
→ Détails : Créer un compte
Une fois connecté à la console :
ak_….monsite.tn, app.monsite.tn).Pas de wildcard
Le check des domaines est strict. *.monsite.tn n’est pas accepté : ajoutez chaque sous-domaine explicitement. localhost doit également être ajouté pour le développement local.
→ Détails : Gérer les clés API · Domaines autorisés
Toutes les requêtes utilisent un paramètre api_key en query string :
https://api.tmaps.tn/geocoding/forward?q=Avenue%20Habib%20Bourguiba%2C%20Tunis&api_key=YOUR_API_KEYcurl "https://api.tmaps.tn/geocoding/forward?q=Avenue%20Habib%20Bourguiba%2C%20Tunis&api_key=YOUR_API_KEY"const url = new URL('https://api.tmaps.tn/geocoding/forward');
url.searchParams.set('q', 'Avenue Habib Bourguiba, Tunis');
url.searchParams.set('api_key', 'YOUR_API_KEY');
const res = await fetch(url);
const data = await res.json();
console.log(data.results[0]);
// { lat: 36.8002, lng: 10.1815, formatted: '...', confidence: 0.95 }import requests
res = requests.get(
'https://api.tmaps.tn/geocoding/forward',
params={
'q': 'Avenue Habib Bourguiba, Tunis',
'api_key': 'YOUR_API_KEY',
},
)
print(res.json()['results'][0])<?php
$query = http_build_query([
'q' => 'Avenue Habib Bourguiba, Tunis',
'api_key' => 'YOUR_API_KEY',
]);
$res = file_get_contents("https://api.tmaps.tn/geocoding/forward?$query");
$data = json_decode($res, true);
print_r($data['results'][0]);Côté serveur, aucun domaine requis
Si vous appelez l’API depuis un backend Node, PHP, Python… (sans header Origin ni Referer), votre clé fonctionne sans restriction de domaine. Les domaines autorisés ne s’appliquent qu’aux appels initiés depuis un navigateur.
Selon votre cas d’usage, plongez dans la référence d’API correspondante :
Comment passer votre clé API, comment fonctionnent les domaines autorisés (Origin/Referer) et comment appeler l'API depuis un serveur.
Toute requête vers l’API TMaps doit être authentifiée à l’aide d’une clé API (api_key), créée depuis la console TMaps.
Une clé API TMaps a la forme suivante :
ak_a1b2c3d4e5f607xxxXXXxXXxxXXLe préfixe ak_ est suivi de 32 caractères hexadécimaux. Considérez votre clé comme un mot de passe : ne la versionnez pas dans un dépôt public et ne l’exposez pas dans des logs côté client si possible.
api_key en query stringTous les endpoints (GET comme POST) acceptent la clé via le paramètre api_key dans la query string.
https://api.tmaps.tn/{endpoint}?api_key=YOUR_API_KEY&...curl "https://api.tmaps.tn/geocoding/forward?q=Tunis&api_key=YOUR_API_KEY"const url = new URL('https://api.tmaps.tn/geocoding/forward');
url.searchParams.set('q', 'Tunis');
url.searchParams.set('api_key', 'YOUR_API_KEY');
const res = await fetch(url);Pas de header Authorization
TMaps n’utilise pas de header Authorization: Bearer …. La clé passe toujours par le paramètre api_key de la query string, y compris pour les requêtes POST.
Pour empêcher qu’une clé exposée dans le code JavaScript d’un site soit réutilisée ailleurs, vous pouvez restreindre une clé à une liste blanche de domaines depuis la console (rubrique Authorized Domains).
À chaque requête, le backend vérifie en cascade :
Origin envoyé par le navigateur ;Referer.Si l’un des deux est présent et ne correspond à aucun domaine autorisé pour la clé, la requête est rejetée avec un statut 403 :
{
"error": "domain not authorized"
}*.monsite.tn n’est pas accepté : ajoutez chaque sous-domaine explicitement (app.monsite.tn, admin.monsite.tn, …).localhost doit être ajouté. Pour le développement local, ajoutez localhost (et 127.0.0.1 si vous l’utilisez) à votre liste de domaines.403.Quand votre code tourne dans un environnement server-side (Node, PHP, Python, Go, mobile natif…), les headers Origin et Referer sont absents de la requête. Dans ce cas, la liste des domaines autorisés est ignorée et la clé fonctionne sans restriction.
Conseil de sécurité
Pour une intégration purement backend, créez une clé dédiée sans aucun domaine autorisé : elle restera utilisable depuis vos serveurs (pas d’Origin) mais sera bloquée côté navigateur si elle fuite dans un repo public.
| Statut | Cause | Body |
|---|---|---|
401 | api_key absent, désactivé ou révoqué | {"error":"missing api_key"} |
403 | Origin/Referer non autorisé, ou requête HTTP | {"error":"domain not authorized"} |
Voir la liste complète sur la page Codes d’erreur.
Inscrivez-vous sur la console TMaps en email + mot de passe ou en un clic via Google.
La console TMaps est l’interface qui vous permet de gérer vos clés API, vos domaines autorisés et de suivre votre consommation. Vous y accédez sur app.tmaps.tn.
Rendez-vous sur app.tmaps.tn/auth/sign-up.

Deux options vous sont proposées :


Le compte Google et le compte email + mot de passe sont distincts : si vous voulez utiliser les deux méthodes, créez deux comptes séparés ou contactez-nous pour les fusionner.
Une fois connecté, vous arrivez sur le tableau de bord de la console. Les sections principales sont accessibles depuis la barre latérale :

Vous êtes prêt à créer votre première clé API. Continuez avec :
Créez, désactivez ou révoquez vos clés API depuis la console TMaps.
Une clé API est l’identifiant unique qui authentifie vos requêtes vers les endpoints TMaps. Cette page explique comment la créer, la désactiver et la révoquer depuis la console.


ak_....
Copiez cette clé dès maintenant
Pour des raisons de sécurité, elle ne sera plus affichée après la fermeture de cette fenêtre. Conservez-la dans un gestionnaire de mots de passe, un coffre-fort ou votre fichier .env. Si vous la perdez, vous devrez générer une nouvelle clé. C’est la valeur que vous passerez en paramètre api_key de chaque requête.
Toutes vos clés sont visibles depuis l’onglet API Keys. Chaque ligne affiche :

Désactiver suspend temporairement l’usage de la clé : tout appel renverra 401. La clé peut être réactivée à tout moment.
⋮) en bout de ligne.
Pour réactiver, ouvrez le même menu et cliquez sur Enable.
La révocation est définitive : la clé ne pourra plus être réactivée. Utilisez-la quand :
⋮).
La révocation est irréversible
Une fois révoquée, la clé est marquée définitivement Revoked et ne peut pas être régénérée. Créez une nouvelle clé pour la remplacer si besoin.
Pour sécuriser une clé exposée au navigateur, ajoutez-lui des domaines autorisés :
Restreignez vos clés API à une liste blanche de domaines pour empêcher leur utilisation depuis un site tiers.
Un domaine autorisé (Authorized Domain) est un nom d’hôte depuis lequel vos clés API sont autorisées à être utilisées. Le check se fait à chaque requête en comparant les headers Origin puis Referer à la liste des domaines liés à la clé.

Saisissez le nom de domaine sans schéma ni chemin :
monsite.tnapp.monsite.tnlocalhosthttps://monsite.tnmonsite.tn/dashboard*.monsite.tn(wildcard non supporté)Cliquez sur Add.

Pas de wildcard
Le check des domaines est strict. Pour autoriser plusieurs sous-domaines, ajoutez chaque sous-domaine séparément (app.monsite.tn, admin.monsite.tn, …).
Localhost en développement
Pour le développement local, ajoutez explicitement localhost (et 127.0.0.1 si vous l’utilisez) à votre liste : sinon vos appels seront rejetés en 403 tant que vous n’êtes pas en production.
Une fois vos domaines ajoutés, vous devez les lier aux clés concernées. Vous pouvez le faire de deux façons :


Le lien entre clés et domaines est N : N :
monsite.tn, app.monsite.tn, localhost).app.monsite.tn).Quand utiliser plusieurs clés sur un même domaine ?
Cela permet d’avoir des clés à durée de vie courte (rotation, A/B testing) tout en partageant la même liste de domaines, ou d’isoler la consommation de plusieurs équipes / produits sur un même site.
À chaque requête authentifiée par une clé qui a au moins un domaine lié, le backend :
Origin de la requête. S’il est présent et figure dans la liste des domaines autorisés → la requête passe.Referer. S’il est présent et figure dans la liste → la requête passe.{"error":"domain not authorized"}.Cas particulier — appels server-to-server (Node, PHP, mobile natif…) : ni Origin ni Referer n’est envoyé. Dans ce cas, la liste de domaines est ignorée et la clé fonctionne sans restriction. Voir Authentification pour le détail.
× à côté du domaine dans la section Authorized Domains. La clé reste active mais ne fonctionnera plus depuis ce domaine.
localhost ajouté.Origin/Referer) et c’est plus clair que de lister manuellement l’absence de check.Tuiles cartographiques au format PNG, prêtes à brancher dans Leaflet, MapLibre GL ou OpenLayers.
L’endpoint Raster Tiles sert des tuiles d’image PNG suivant la convention XYZ standard (z = zoom, x / y = coordonnées). Compatible avec toutes les bibliothèques cartographiques web et mobile.
https://tiles.tmaps.tn/r-tile/{z}/{x}/{y}?api_key=YOUR_API_KEYParamètres de chemin
| Param | Type | Requis | Défaut | Description |
|---|---|---|---|---|
z | integer | oui | — | Niveau de zoom (entre 0 et 18). |
x | integer | oui | — | Coordonnée X de la tuile dans la grille XYZ. |
y | integer | oui | — | Coordonnée Y de la tuile dans la grille XYZ. |
Paramètres de query
| Param | Type | Requis | Défaut | Description |
|---|---|---|---|---|
api_key | string | oui | — | Votre clé API TMaps. |
image/png0 → 18@2x) : non supporté pour le momentDétection de la limite de zoom
Quand vous configurez votre carte, fixez maxZoom à 18. Au-delà, les tuiles ne sont plus disponibles et la couche s’affichera vide ou en quadrillage gris.
Une réponse réussie est un fichier PNG (Content-Type: image/png).
En cas d’erreur, vous recevez un statut HTTP 4xx/5xx avec un body JSON :
{ "error": "missing api_key" }Voir la liste complète sur la page Codes d’erreur.
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';
const map = L.map('map').setView([36.8002, 10.1815], 12); // Tunis
L.tileLayer(
'https://tiles.tmaps.tn/r-tile/{z}/{x}/{y}?api_key=YOUR_API_KEY',
{
maxZoom: 18,
attribution: '© TMaps',
}
).addTo(map);<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet"><\/script>
<div id="map" style="height: 400px"></div>
<script>
const map = L.map('map').setView([36.8002, 10.1815], 12);
L.tileLayer(
'https://tiles.tmaps.tn/r-tile/{z}/{x}/{y}?api_key=YOUR_API_KEY',
{ maxZoom: 18 }
).addTo(map);
<\/script>MapLibre supporte les couches raster via la propriété sources du style :
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
const map = new maplibregl.Map({
container: 'map',
center: [10.1815, 36.8002],
zoom: 12,
maxZoom: 18,
style: {
version: 8,
sources: {
'tmaps-raster': {
type: 'raster',
tiles: ['https://tiles.tmaps.tn/r-tile/{z}/{x}/{y}?api_key=YOUR_API_KEY'],
tileSize: 256,
},
},
layers: [{ id: 'tmaps-raster', type: 'raster', source: 'tmaps-raster' }],
},
});import 'ol/ol.css';
import { Map, View } from 'ol';
import TileLayer from 'ol/layer/Tile';
import XYZ from 'ol/source/XYZ';
import { fromLonLat } from 'ol/proj';
new Map({
target: 'map',
layers: [
new TileLayer({
source: new XYZ({
url: 'https://tiles.tmaps.tn/r-tile/{z}/{x}/{y}?api_key=YOUR_API_KEY',
maxZoom: 18,
}),
}),
],
view: new View({
center: fromLonLat([10.1815, 36.8002]),
zoom: 12,
}),
});Tous les SDK mobiles qui supportent les couches XYZ (MapLibre Native, MapKit JS, react-native-maps en mode UrlTemplate, etc.) sont compatibles. Utilisez le même template :
https://tiles.tmaps.tn/r-tile/{z}/{x}/{y}?api_key=YOUR_API_KEYCache et performance
Les tuiles raster sont servies avec des en-têtes Cache-Control longue durée. Si vous intégrez côté mobile, activez le cache disque de votre lib pour réduire la consommation data.
Pour tester l’API et l’utiliser en production, créez un compte puis générez une clé API depuis la console TMaps. Pensez à ajouter localhost à vos domaines autorisés si vous testez en local depuis un navigateur.
Quatre styles vectoriels (streets, dark, terrain, sunny) consommables avec MapLibre GL pour des cartes ultra-rapides et personnalisables.
Les tuiles vectorielles TMaps sont distribuées au format Mapbox Vector Tile (.pbf) et encapsulées dans un manifest TileJSON / Mapbox Style Spec prêt à être consommé par MapLibre GL.
Quatre styles sont disponibles, chacun avec sa palette et sa thématique.
Chaque style est exposé sous la forme d’un fichier JSON conforme à la Mapbox Style Specification :
https://tiles.tmaps.tn/v-tile/{style}.json?api_key=YOUR_API_KEYL’URL des tuiles .pbf est référencée dans la propriété sources du JSON renvoyé : aucun appel manuel à faire, MapLibre gère tout automatiquement.
| Style | URL | Description |
|---|---|---|
| streets | https://tiles.tmaps.tn/v-tile/streets.json?api_key=… | Carte de référence claire, optimisée pour la lecture des rues et POI urbains. |
| dark | https://tiles.tmaps.tn/v-tile/dark.json?api_key=… | Variante sombre — idéale pour les dashboards et apps en mode nuit. |
| terrain | https://tiles.tmaps.tn/v-tile/terrain.json?api_key=… | Met en avant le relief, les cours d’eau et la topographie. |
| sunny | https://tiles.tmaps.tn/v-tile/sunny.json?api_key=… | Palette chaleureuse, parfaite pour le tourisme et le retail. |
Switch de style à chaud
MapLibre permet de changer le style sans détruire la carte (map.setStyle(url)), ce qui rend très simple un toggle dark/light dans votre application.
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
const map = new maplibregl.Map({
container: 'map',
style: 'https://tiles.tmaps.tn/v-tile/streets.json?api_key=YOUR_API_KEY',
center: [10.1815, 36.8002], // Tunis
zoom: 12,
});
map.addControl(new maplibregl.NavigationControl(), 'top-right');<link href="https://unpkg.com/maplibre-gl/dist/maplibre-gl.css" rel="stylesheet" />
<script src="https://unpkg.com/maplibre-gl"><\/script>
<div id="map" style="height: 400px"></div>
<script>
const map = new maplibregl.Map({
container: 'map',
style: 'https://tiles.tmaps.tn/v-tile/streets.json?api_key=YOUR_API_KEY',
center: [10.1815, 36.8002],
zoom: 12,
});
<\/script>import { useEffect, useRef } from 'react';
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
export function TmapsVectorMap() {
const ref = useRef(null);
useEffect(() => {
const map = new maplibregl.Map({
container: ref.current,
style: 'https://tiles.tmaps.tn/v-tile/streets.json?api_key=YOUR_API_KEY',
center: [10.1815, 36.8002],
zoom: 12,
});
return () => map.remove();
}, []);
return <div ref={ref} style={{ height: 400 }} />;
}const styles = {
light: 'https://tiles.tmaps.tn/v-tile/streets.json?api_key=YOUR_API_KEY',
dark: 'https://tiles.tmaps.tn/v-tile/dark.json?api_key=YOUR_API_KEY',
};
document.querySelector('#toggle-dark').addEventListener('click', () => {
const current = map.getStyle().name;
map.setStyle(current === 'dark' ? styles.light : styles.dark);
});MapLibre Native (iOS, Android) et MapLibre RN consomment directement le style.json. Passez simplement l’URL complète à votre constructeur :
let url = URL(string: "https://tiles.tmaps.tn/v-tile/streets.json?api_key=YOUR_API_KEY")!
let mapView = MLNMapView(frame: view.bounds, styleURL: url)val mapView = MapView(context)
mapView.getMapAsync { map ->
map.setStyle(Style.Builder().fromUri(
"https://tiles.tmaps.tn/v-tile/streets.json?api_key=YOUR_API_KEY"
))
}import MapLibreGL from '@maplibre/maplibre-react-native';
<MapLibreGL.MapView
styleURL="https://tiles.tmaps.tn/v-tile/streets.json?api_key=YOUR_API_KEY"
style={{ flex: 1 }}
/>Le JSON renvoyé suit la Mapbox Style Spec, donc vous pouvez :
curl https://tiles.tmaps.tn/v-tile/streets.json?api_key=…).layers (couleurs, polices, visibilité par zoom)..pbf d’origine.Limites de personnalisation
L’URL des tuiles .pbf dans sources doit rester pointée vers tiles.tmaps.tn avec votre api_key — c’est elle qui authentifie votre consommation. Vous pouvez en revanche modifier librement layers, glyphs et sprite si vous hébergez vos propres ressources.
.pbf)0 → 18style.jsonPour tester l’API et l’utiliser en production, créez un compte puis générez une clé API depuis la console TMaps. Pensez à ajouter localhost à vos domaines autorisés si vous testez en local depuis un navigateur.
Convertissez une adresse libre en coordonnées GPS précises, avec un score de confiance et la décomposition (commune, délégation, gouvernorat).
L’endpoint Forward Geocoding convertit une adresse en texte libre en coordonnées géographiques (latitude / longitude). Il est calibré pour le découpage administratif tunisien (commune, délégation, gouvernorat).
https://api.tmaps.tn/geocoding/forward?q=...&api_key=YOUR_API_KEYParamètres de query
| Param | Type | Requis | Défaut | Description |
|---|---|---|---|---|
q | string | oui | — | Texte à géocoder. Peut être une adresse, un POI, une commune, une rue. Exemples : Avenue Habib Bourguiba, Tunis, Médina de Tunis. |
api_key | string | oui | — | Votre clé API TMaps. |
country | string | — | TN | Code ISO 3166-1 alpha-2 du pays cible (ex. TN). Restreint la recherche à ce pays. |
limit | integer | — | 5 | Nombre maximum de résultats à renvoyer (1 → 20). |
lang | string | — | fr | Langue des libellés et adresses formatées : fr, en ou ar. |
proximity | string | — | — | Coordonnées lat,lng pour favoriser les résultats proches d'un point (ex. la position de l'utilisateur). |
bbox | string | — | — | Boîte englobante minLng,minLat,maxLng,maxLat pour restreindre la recherche à une zone. |
type | string | — | — | Filtre par type de résultat : address, street, poi, locality. |
curl "https://api.tmaps.tn/geocoding/forward?q=Avenue%20Habib%20Bourguiba%2C%20Tunis&country=TN&limit=3&lang=fr&api_key=YOUR_API_KEY"const url = new URL('https://api.tmaps.tn/geocoding/forward');
url.searchParams.set('q', 'Avenue Habib Bourguiba, Tunis');
url.searchParams.set('country', 'TN');
url.searchParams.set('limit', '3');
url.searchParams.set('lang', 'fr');
url.searchParams.set('api_key', 'YOUR_API_KEY');
const res = await fetch(url);
const data = await res.json();
const best = data.results[0];
console.log(best.lat, best.lng, best.confidence);import requests
res = requests.get('https://api.tmaps.tn/geocoding/forward', params={
'q': 'Avenue Habib Bourguiba, Tunis',
'country': 'TN',
'limit': 3,
'lang': 'fr',
'api_key': 'YOUR_API_KEY',
})
data = res.json()
best = data['results'][0]
print(best['lat'], best['lng'], best['confidence'])<?php
$query = http_build_query([
'q' => 'Avenue Habib Bourguiba, Tunis',
'country' => 'TN',
'limit' => 3,
'lang' => 'fr',
'api_key' => 'YOUR_API_KEY',
]);
$res = file_get_contents("https://api.tmaps.tn/geocoding/forward?$query");
$data = json_decode($res, true);
$best = $data['results'][0];
echo "{$best['lat']}, {$best['lng']} ({$best['confidence']})";{
"query": "Avenue Habib Bourguiba, Tunis",
"results": [
{
"lat": 36.8002,
"lng": 10.1815,
"formatted": "Avenue Habib Bourguiba, 1001 Tunis, Tunisie",
"confidence": 0.95,
"type": "street",
"components": {
"street": "Avenue Habib Bourguiba",
"postcode": "1001",
"commune": "Tunis",
"delegation": "Tunis Médina",
"governorate": "Tunis",
"country": "TN"
},
"bbox": [10.1750, 36.7980, 10.1880, 36.8030]
}
]
}Champ d'un résultat
| Param | Type | Requis | Défaut | Description |
|---|---|---|---|---|
lat | number | — | — | Latitude WGS84 en degrés décimaux. |
lng | number | — | — | Longitude WGS84 en degrés décimaux. |
formatted | string | — | — | Adresse complète formatée pour l'affichage. |
confidence | number | — | — | Score de confiance entre 0 et 1. Au-delà de 0.9, considérez le résultat comme fiable. |
type | string | — | — | Type d'objet géocodé : address, street, poi, locality. |
components | object | — | — | Détail administratif : street, postcode, commune, delegation, governorate, country. |
bbox | array | — | — | Boîte englobante du résultat [minLng, minLat, maxLng, maxLat]. |
Filtrer par score de confiance
Pour des cas d’usage transactionnels (livraison, e-commerce), n’enregistrez les coordonnées que si confidence >= 0.85 et présentez à l’utilisateur les autres résultats à valider.
| Statut | Cause |
|---|---|
400 | Paramètre q manquant ou vide |
401 | api_key manquant ou révoqué |
403 | Domaine non autorisé |
Voir Codes d’erreur pour la liste complète.
Convertissez une paire de coordonnées GPS en adresse postale lisible (rue, commune, délégation, gouvernorat).
L’endpoint Reverse Geocoding prend une paire lat / lng et renvoie l’adresse postale correspondante avec sa décomposition administrative (commune, délégation, gouvernorat).
https://api.tmaps.tn/geocoding/reverse?lat=...&lng=...&api_key=YOUR_API_KEYParamètres de query
| Param | Type | Requis | Défaut | Description |
|---|---|---|---|---|
lat | number | oui | — | Latitude WGS84 en degrés décimaux (entre -90 et 90). |
lng | number | oui | — | Longitude WGS84 en degrés décimaux (entre -180 et 180). |
api_key | string | oui | — | Votre clé API TMaps. |
lang | string | — | fr | Langue de l'adresse formatée : fr, en ou ar. |
type | string | — | — | Type cible : address, street, poi, locality. Utile pour forcer un résultat locality quand on ne veut que la commune. |
limit | integer | — | 1 | Nombre maximum de résultats (1 → 5). |
curl "https://api.tmaps.tn/geocoding/reverse?lat=36.8002&lng=10.1815&lang=fr&api_key=YOUR_API_KEY"const url = new URL('https://api.tmaps.tn/geocoding/reverse');
url.searchParams.set('lat', '36.8002');
url.searchParams.set('lng', '10.1815');
url.searchParams.set('lang', 'fr');
url.searchParams.set('api_key', 'YOUR_API_KEY');
const res = await fetch(url);
const { results } = await res.json();
console.log(results[0].formatted);
// â "Avenue Habib Bourguiba, 1001 Tunis, Tunisie"import requests
res = requests.get('https://api.tmaps.tn/geocoding/reverse', params={
'lat': 36.8002,
'lng': 10.1815,
'lang': 'fr',
'api_key': 'YOUR_API_KEY',
})
print(res.json()['results'][0]['formatted'])<?php
$query = http_build_query([
'lat' => 36.8002,
'lng' => 10.1815,
'lang' => 'fr',
'api_key' => 'YOUR_API_KEY',
]);
$res = file_get_contents("https://api.tmaps.tn/geocoding/reverse?$query");
$data = json_decode($res, true);
echo $data['results'][0]['formatted'];{
"query": { "lat": 36.8002, "lng": 10.1815 },
"results": [
{
"lat": 36.8002,
"lng": 10.1815,
"formatted": "Avenue Habib Bourguiba, 1001 Tunis, Tunisie",
"distance": 4.2,
"type": "address",
"components": {
"street": "Avenue Habib Bourguiba",
"postcode": "1001",
"commune": "Tunis",
"delegation": "Tunis Médina",
"governorate": "Tunis",
"country": "TN"
}
}
]
}Champ d'un résultat
| Param | Type | Requis | Défaut | Description |
|---|---|---|---|---|
lat | number | — | — | Latitude du point trouvé (peut différer de la requête si snap sur un objet). |
lng | number | — | — | Longitude du point trouvé. |
formatted | string | — | — | Adresse complète formatée. |
distance | number | — | — | Distance en mètres entre la requête et le point trouvé. |
type | string | — | — | Type de résultat : address, street, poi, locality. |
components | object | — | — | Détail administratif : street, postcode, commune, delegation, governorate, country. |
Snap sur la rue ou le bâtiment le plus proche
Si la coordonnée envoyée tombe au milieu d’une rue ou à 30 m d’un bâtiment, l’API renvoie le point le plus proche pertinent et expose la distance dans distance.
| Statut | Cause |
|---|---|
400 | lat ou lng manquant, ou hors plage |
401 | api_key manquant ou révoqué |
403 | Domaine non autorisé |
404 | Aucune adresse trouvée à proximité |
Voir Codes d’erreur pour la liste complète.
Trouvez les points d'intérêt (POI) autour d'un point GPS, filtrables par catégorie : restaurants, écoles, hôpitaux, transports...
L’endpoint Nearby retourne les points d’intérêt (POI) situés autour d’un point GPS, triés par distance croissante. Il est calibré pour le contexte tunisien (commerces, services publics, transport, santé).
https://api.tmaps.tn/geocoding/nearby?lat=...&lng=...&radius=...&api_key=YOUR_API_KEYParamètres de query
| Param | Type | Requis | Défaut | Description |
|---|---|---|---|---|
lat | number | oui | — | Latitude du centre de la recherche. |
lng | number | oui | — | Longitude du centre de la recherche. |
radius | integer | oui | — | Rayon de recherche en mètres (max 10000). |
api_key | string | oui | — | Votre clé API TMaps. |
categories | string | — | — | Filtre par catégories, séparées par une virgule (ex. restaurant,pharmacy). Voir la liste ci-dessous. |
q | string | — | — | Filtre textuel sur le nom du POI (ex. carrefour). |
limit | integer | — | 20 | Nombre maximum de résultats (1 → 100). |
lang | string | — | fr | Langue des libellés : fr, en ou ar. |
| Catégorie | Description |
|---|---|
restaurant | Restaurants, fast-food, snacks |
cafe | Cafés et salons de thé |
school | Écoles, lycées, universités |
hospital | Hôpitaux, cliniques |
pharmacy | Pharmacies |
bank | Banques, distributeurs |
atm | Distributeurs automatiques (ATM) |
fuel | Stations-service |
hotel | Hôtels et hébergements |
parking | Parkings publics et privés |
transit | Stations de bus, métro, train, taxis |
municipality | Mairies et services municipaux |
health | Centres de santé, laboratoires |
education | Tous types d’établissements éducatifs |
shopping | Centres commerciaux, supermarchés, boutiques |
culture | Musées, théâtres, cinémas, sites historiques |
mosque | Mosquées |
place_of_worship | Lieux de culte (toutes confessions) |
Combiner plusieurs catégories
Vous pouvez passer plusieurs catégories séparées par une virgule : categories=restaurant,cafe,bakery. La recherche fait une union (OR).
curl "https://api.tmaps.tn/geocoding/nearby?lat=36.8002&lng=10.1815&radius=1500&categories=pharmacy,hospital&limit=10&api_key=YOUR_API_KEY"const url = new URL('https://api.tmaps.tn/geocoding/nearby');
url.searchParams.set('lat', '36.8002');
url.searchParams.set('lng', '10.1815');
url.searchParams.set('radius', '1500');
url.searchParams.set('categories', 'pharmacy,hospital');
url.searchParams.set('limit', '10');
url.searchParams.set('api_key', 'YOUR_API_KEY');
const res = await fetch(url);
const { results } = await res.json();
results.forEach((p) => {
console.log(`${p.name} â ${p.distance} m`);
});import requests
res = requests.get('https://api.tmaps.tn/geocoding/nearby', params={
'lat': 36.8002,
'lng': 10.1815,
'radius': 1500,
'categories': 'pharmacy,hospital',
'limit': 10,
'api_key': 'YOUR_API_KEY',
})
for p in res.json()['results']:
print(f"{p['name']} â {p['distance']} m"){
"query": { "lat": 36.8002, "lng": 10.1815, "radius": 1500 },
"count": 3,
"results": [
{
"id": "poi_42018",
"name": "Pharmacie de l'Avenue",
"category": "pharmacy",
"lat": 36.7995,
"lng": 10.1820,
"distance": 75,
"address": "Avenue Habib Bourguiba, Tunis",
"phone": "+216 71 245 678",
"opening_hours": "Lun-Sam 08:30-19:00"
},
{
"id": "poi_77110",
"name": "Hôpital Charles Nicolle",
"category": "hospital",
"lat": 36.8000,
"lng": 10.1815,
"distance": 220,
"address": "Boulevard du 9 Avril 1938, Tunis",
"phone": "+216 71 562 000",
"opening_hours": "24/7"
},
{
"id": "poi_88231",
"name": "Pharmacie Centrale",
"category": "pharmacy",
"lat": 36.8021,
"lng": 10.1798,
"distance": 310,
"address": "Rue de la Liberté, Tunis"
}
]
}Champ d'un POI
| Param | Type | Requis | Défaut | Description |
|---|---|---|---|---|
id | string | — | — | Identifiant stable du POI dans la base TMaps. |
name | string | — | — | Nom commercial du POI. |
category | string | — | — | Catégorie (voir liste ci-dessus). |
lat | number | — | — | Latitude du POI. |
lng | number | — | — | Longitude du POI. |
distance | number | — | — | Distance en mètres depuis le point de recherche. |
address | string | — | — | Adresse formatée du POI. |
phone | string | — | — | Téléphone (optionnel). |
opening_hours | string | — | — | Horaires d'ouverture (optionnel, format libre). |
| Statut | Cause |
|---|---|
400 | lat, lng ou radius manquant, ou radius au-delà de 10000 |
401 | api_key manquant ou révoqué |
403 | Domaine non autorisé |
Voir Codes d’erreur pour la liste complète.
Calculez un itinéraire optimal entre deux points ou plus, avec turn-by-turn, distance, durée et géométrie.
L’endpoint Direction calcule l’itinéraire optimal entre un point de départ et un ou plusieurs points d’arrivée (waypoints). Il renvoie la distance totale, la durée estimée, la géométrie et — sur demande — les instructions turn-by-turn.
Deux variantes équivalentes :
https://api.tmaps.tn/routing/direction?from=lat,lng&to=lat,lng&api_key=YOUR_API_KEYhttps://api.tmaps.tn/routing/direction?api_key=YOUR_API_KEYUtilisez GET pour les itinéraires simples (2 points). Utilisez POST dès que vous avez plusieurs waypoints ou des options avancées.
Paramètres communs (query GET ou body POST)
| Param | Type | Requis | Défaut | Description |
|---|---|---|---|---|
api_key | string | oui | — | Votre clé API TMaps (toujours en query string, même en POST). |
from | string | — | — | [GET] Point de départ lat,lng. |
to | string | — | — | [GET] Point d'arrivée lat,lng. |
waypoints | array | — | — | [POST] Liste ordonnée de points { lat, lng } (min 2, max 25). |
profile | string | — | driving | Profil de transport : driving, walking, cycling, truck. |
geometry | string | — | polyline | Format de la géométrie de retour : polyline (Google polyline encodé) ou geojson. |
steps | boolean | — | false | Si true, renvoie les instructions turn-by-turn. |
alternatives | boolean | — | false | Si true, renvoie jusqu'à 2 itinéraires alternatifs. |
avoid | string | — | — | Liste séparée par virgule des éléments à éviter : tolls, highways, ferries. |
language | string | — | fr | Langue des instructions : fr, en, ar. |
curl "https://api.tmaps.tn/routing/direction?from=36.8002,10.1815&to=36.8528,10.3261&profile=driving&api_key=YOUR_API_KEY"const url = new URL('https://api.tmaps.tn/routing/direction');
url.searchParams.set('from', '36.8002,10.1815'); // Tunis centre
url.searchParams.set('to', '36.8528,10.3261'); // Carthage
url.searchParams.set('profile', 'driving');
url.searchParams.set('api_key', 'YOUR_API_KEY');
const res = await fetch(url);
const data = await res.json();
console.log(`${data.distance} m, ${data.duration} s`);curl -X POST "https://api.tmaps.tn/routing/direction?api_key=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"waypoints": [
{ "lat": 36.7992, "lng": 10.1709 },
{ "lat": 36.8094, "lng": 10.1400 },
{ "lat": 36.8528, "lng": 10.3261 }
],
"profile": "driving",
"steps": true,
"geometry": "geojson"
}'const res = await fetch(
'https://api.tmaps.tn/routing/direction?api_key=YOUR_API_KEY',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
waypoints: [
{ lat: 36.7992, lng: 10.1709 }, // Médina de Tunis
{ lat: 36.8094, lng: 10.1400 }, // Musée du Bardo
{ lat: 36.8528, lng: 10.3261 }, // Carthage
],
profile: 'driving',
steps: true,
geometry: 'geojson',
}),
}
);
const data = await res.json();
console.log(`${data.distance / 1000} km en ${Math.round(data.duration / 60)} min`);import requests
res = requests.post(
'https://api.tmaps.tn/routing/direction',
params={'api_key': 'YOUR_API_KEY'},
json={
'waypoints': [
{'lat': 36.7992, 'lng': 10.1709},
{'lat': 36.8094, 'lng': 10.1400},
{'lat': 36.8528, 'lng': 10.3261},
],
'profile': 'driving',
'steps': True,
'geometry': 'geojson',
},
)
data = res.json()
print(f"{data['distance'] / 1000} km en {round(data['duration'] / 60)} min"){
"distance": 19420,
"duration": 1830,
"geometry": {
"type": "LineString",
"coordinates": [
[10.1709, 36.7992],
[10.1655, 36.8021],
[10.1400, 36.8094],
[10.2630, 36.8420],
[10.3261, 36.8528]
]
},
"legs": [
{
"distance": 4870,
"duration": 540,
"from": { "lat": 36.7992, "lng": 10.1709 },
"to": { "lat": 36.8094, "lng": 10.1400 },
"steps": [
{ "instruction": "Continuez sur Avenue Habib Bourguiba", "distance": 320, "duration": 50 },
{ "instruction": "Tournez à droite sur Rue de Carthage", "distance": 180, "duration": 30 }
]
},
{
"distance": 14550,
"duration": 1290,
"from": { "lat": 36.8094, "lng": 10.1400 },
"to": { "lat": 36.8528, "lng": 10.3261 },
"steps": [
{ "instruction": "Prenez l'autoroute A1 direction Carthage", "distance": 12300, "duration": 850 }
]
}
]
}Champs racine
| Param | Type | Requis | Défaut | Description |
|---|---|---|---|---|
distance | number | — | — | Distance totale en mètres. |
duration | number | — | — | Durée estimée totale en secondes. |
geometry | string|object | — | — | Polyline encodée (par défaut) ou objet GeoJSON LineString si geometry=geojson. |
legs | array | — | — | Sous-itinéraires entre chaque paire de waypoints consécutifs. |
alternatives | array | — | — | Présent uniquement si alternatives=true : liste d'itinéraires alternatifs (mêmes champs que la racine). |
Décoder la polyline
Si vous gardez geometry=polyline (par défaut), utilisez la lib polyline pour la décoder côté client. Sinon passez geometry=geojson et tracez directement la LineString.
| Profil | Description |
|---|---|
driving | Voiture (par défaut). Tient compte du sens de circulation et des restrictions urbaines. |
walking | Piéton. Inclut allées, escaliers et zones piétonnes. |
cycling | Vélo. Privilégie les voies cyclables quand elles existent. |
truck | Poids lourd. Évite les routes interdites aux camions et tient compte des limitations de tonnage. |
walking et cycling pour des apps urbaines.truck pour les flottes de poids lourds.| Statut | Cause |
|---|---|
400 | Coordonnées manquantes ou hors plage, profil inconnu |
401 | api_key manquant ou révoqué |
403 | Domaine non autorisé |
404 | Aucun itinéraire trouvé entre les points (zone non couverte) |
Voir Codes d’erreur pour la liste complète.
Optimisez l'ordre de visite d'une liste de points pour minimiser la distance totale ou la durée totale (problème du voyageur de commerce).
L’endpoint Optimized Routing réordonne une liste de points pour calculer la tournée optimale — typiquement l’ordre de livraison qui minimise la distance ou la durée totale. C’est une solution au problème du voyageur de commerce (TSP).
https://api.tmaps.tn/routing/optimized?api_key=YOUR_API_KEYBody JSON
| Param | Type | Requis | Défaut | Description |
|---|---|---|---|---|
origin | object | oui | — | Point de départ { lat, lng }. Reste fixe dans la tournée optimisée. |
waypoints | array | oui | — | Liste de points { lat, lng } à réordonner (max 50 waypoints). |
destination | object | — | — | Point d'arrivée fixe { lat, lng }. Si omis, la tournée se termine au dernier waypoint optimisé. |
profile | string | — | driving | Profil de transport : driving, walking, cycling, truck. |
optimize | string | — | duration | Critère d'optimisation : duration ou distance. |
roundtrip | boolean | — | false | Si true, la tournée revient au point de départ. |
geometry | string | — | polyline | Format de la géométrie de retour : polyline ou geojson. |
steps | boolean | — | false | Si true, renvoie les instructions turn-by-turn pour chaque leg. |
VRP avancé : roadmap
La version actuelle traite un TSP simple (un seul véhicule, sans contraintes). Les fenêtres temporelles (time windows), les capacités véhicule et la flotte multi-véhicules sont prévues dans une future version. Si vous avez besoin de ces fonctionnalités, contactez-nous.
curl -X POST "https://api.tmaps.tn/routing/optimized?api_key=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"origin": { "lat": 36.8355, "lng": 10.2261 },
"waypoints": [
{ "lat": 36.8485, "lng": 10.1712 },
{ "lat": 36.8644, "lng": 10.1808 },
{ "lat": 36.8664, "lng": 10.1938 },
{ "lat": 36.8779, "lng": 10.2024 }
],
"profile": "driving",
"optimize": "duration",
"roundtrip": true
}'const res = await fetch(
'https://api.tmaps.tn/routing/optimized?api_key=YOUR_API_KEY',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
origin: { lat: 36.8355, lng: 10.2261 }, // Dépôt RapidoTN
waypoints: [
{ lat: 36.8485, lng: 10.1712 }, // Client A
{ lat: 36.8644, lng: 10.1808 }, // Client B
{ lat: 36.8664, lng: 10.1938 }, // Client C
{ lat: 36.8779, lng: 10.2024 }, // Client D
],
profile: 'driving',
optimize: 'duration',
roundtrip: true,
}),
}
);
const data = await res.json();
console.log('Ordre optimal :', data.order);
console.log(`${data.distance / 1000} km, ${Math.round(data.duration / 60)} min`);import requests
res = requests.post(
'https://api.tmaps.tn/routing/optimized',
params={'api_key': 'YOUR_API_KEY'},
json={
'origin': {'lat': 36.8355, 'lng': 10.2261},
'waypoints': [
{'lat': 36.8485, 'lng': 10.1712},
{'lat': 36.8644, 'lng': 10.1808},
{'lat': 36.8664, 'lng': 10.1938},
{'lat': 36.8779, 'lng': 10.2024},
],
'profile': 'driving',
'optimize': 'duration',
'roundtrip': True,
},
)
data = res.json()
print('Ordre :', data['order'])
print(f"{data['distance'] / 1000} km, {round(data['duration'] / 60)} min"){
"distance": 14820,
"duration": 1680,
"order": [2, 0, 3, 1],
"geometry": "ahvqEi}_iL...",
"legs": [
{
"from": { "lat": 36.8355, "lng": 10.2261 },
"to": { "lat": 36.8664, "lng": 10.1938 },
"distance": 3120,
"duration": 380
},
{
"from": { "lat": 36.8664, "lng": 10.1938 },
"to": { "lat": 36.8485, "lng": 10.1712 },
"distance": 2940,
"duration": 320
}
]
}order est un tableau d’indices (zéro-indexés) qui décrit l’ordre optimisé dans lequel visiter les waypoints d’origine. Dans l’exemple : visitez d’abord waypoints[2], puis waypoints[0], puis waypoints[3], puis waypoints[1].distance et duration sont les totaux pour la tournée complète (origine → tous les waypoints dans l’ordre optimisé → éventuelle destination ou retour).legs détaille chaque segment dans l’ordre optimisé.Ré-ordonner côté client
Pour afficher la tournée à un livreur, projetez order sur votre liste d’origine : const sorted = order.map(i => waypoints[i]).
| Statut | Cause |
|---|---|
400 | Body invalide, plus de 50 waypoints |
401 | api_key manquant ou révoqué |
403 | Domaine non autorisé |
404 | Pas d’itinéraire calculable (au moins un waypoint hors couverture) |
Voir Codes d’erreur pour la liste complète.
Calculez la zone géographique atteignable depuis un point en N minutes ou N kilomètres. Réponse au format GeoJSON Polygon.
L’endpoint Isochrone calcule la zone atteignable depuis un point d’origine en un certain temps (en minutes) ou une certaine distance (en kilomètres). Le résultat est un polygone GeoJSON prêt à afficher sur une carte.
https://api.tmaps.tn/routing/isochrone?api_key=YOUR_API_KEYBody JSON
| Param | Type | Requis | Défaut | Description |
|---|---|---|---|---|
origin | object | oui | — | Point de départ { lat, lng }. |
contours | array | oui | — | Liste de contours à calculer. Chaque contour est { time: minutes } ou { distance: km }. Vous pouvez en demander plusieurs dans une même requête. |
profile | string | — | driving | Profil de transport : driving, walking, cycling, truck. |
colors | array | — | — | Couleur HTML (hex) à associer à chaque contour pour faciliter le rendu (ex. ['#22c55e', '#f59e0b', '#ef4444']). |
Limites
curl -X POST "https://api.tmaps.tn/routing/isochrone?api_key=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"origin": { "lat": 36.8002, "lng": 10.1815 },
"contours": [{ "time": 15 }],
"profile": "driving"
}'const res = await fetch(
'https://api.tmaps.tn/routing/isochrone?api_key=YOUR_API_KEY',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
origin: { lat: 36.8002, lng: 10.1815 },
contours: [{ time: 15 }],
profile: 'driving',
}),
}
);
const geojson = await res.json();
// Affichage sur MapLibre
map.addSource('catchment', { type: 'geojson', data: geojson });
map.addLayer({
id: 'catchment-fill',
type: 'fill',
source: 'catchment',
paint: { 'fill-color': '#22c55e', 'fill-opacity': 0.3 },
});import requests
res = requests.post(
'https://api.tmaps.tn/routing/isochrone',
params={'api_key': 'YOUR_API_KEY'},
json={
'origin': {'lat': 36.8002, 'lng': 10.1815},
'contours': [{'time': 15}],
'profile': 'driving',
},
)
geojson = res.json()
# â ready-to-render FeatureCollectionconst res = await fetch(
'https://api.tmaps.tn/routing/isochrone?api_key=YOUR_API_KEY',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
origin: { lat: 36.8002, lng: 10.1815 },
contours: [
{ time: 5 },
{ time: 10 },
{ time: 15 },
],
profile: 'driving',
colors: ['#22c55e', '#f59e0b', '#ef4444'],
}),
}
);
const geojson = await res.json();
// â 3 features dans le FeatureCollectionLa réponse est un FeatureCollection GeoJSON : une feature par contour demandé, dans le même ordre que la requête.
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"contour": 15,
"metric": "time",
"color": "#22c55e"
},
"geometry": {
"type": "Polygon",
"coordinates": [[
[10.0801, 36.8412],
[10.1240, 36.8650],
[10.2308, 36.8580],
[10.2620, 36.8011],
[10.2210, 36.7530],
[10.1100, 36.7480],
[10.0801, 36.8412]
]]
}
}
]
}Properties d'une feature
| Param | Type | Requis | Défaut | Description |
|---|---|---|---|---|
contour | number | — | — | Valeur du contour : nombre de minutes ou nombre de kilomètres. |
metric | string | — | — | time ou distance selon ce qui a été demandé. |
color | string | — | — | Couleur associée au contour, si fournie en entrée. Pratique pour styliser directement la couche cartographique. |
Ordre d'affichage
Si vous demandez plusieurs contours empilés, dessinez le plus grand (15 min) en arrière-plan et le plus petit (5 min) au premier plan, pour obtenir un effet de niveaux concentriques.
| Statut | Cause |
|---|---|
400 | origin manquant, time > 60 ou distance > 50 |
401 | api_key manquant ou révoqué |
403 | Domaine non autorisé |
404 | Origine hors zone de couverture |
Voir Codes d’erreur pour la liste complète.
Calculez en un seul appel les distances et durées entre N origines et M destinations.
L’endpoint Distance Matrix calcule en une seule requête la distance et la durée entre chaque paire (origine × destination). Idéal pour :
https://api.tmaps.tn/distance-matrix?api_key=YOUR_API_KEYBody JSON
| Param | Type | Requis | Défaut | Description |
|---|---|---|---|---|
origins | array | oui | — | Liste de points { lat, lng } (max 25). |
destinations | array | oui | — | Liste de points { lat, lng } (max 25). |
profile | string | — | driving | Profil de transport : driving, walking, cycling, truck. |
metrics | array | — | ["duration","distance"] | Mesures à renvoyer. Au moins l'une des deux : duration, distance. |
Limite de taille
Maximum 25 origines × 25 destinations par requête, soit 625 paires au total. Pour des matrices plus grandes, découpez en lots et fusionnez les résultats côté client.
curl -X POST "https://api.tmaps.tn/distance-matrix?api_key=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"origins": [
{ "lat": 36.8280, "lng": 10.2100 },
{ "lat": 36.8450, "lng": 10.1850 },
{ "lat": 36.8094, "lng": 10.1400 }
],
"destinations": [
{ "lat": 36.8000, "lng": 10.1815 }
],
"profile": "driving"
}'const ambulances = [
{ id: 'A-01', lat: 36.8280, lng: 10.2100 },
{ id: 'A-02', lat: 36.8450, lng: 10.1850 },
{ id: 'A-03', lat: 36.8094, lng: 10.1400 },
];
const patient = { lat: 36.8000, lng: 10.1815 };
const res = await fetch(
'https://api.tmaps.tn/distance-matrix?api_key=YOUR_API_KEY',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
origins: ambulances.map(({ lat, lng }) => ({ lat, lng })),
destinations: [patient],
profile: 'driving',
}),
}
);
const { durations } = await res.json();
const fastestIdx = durations
.map((row) => row[0])
.reduce((best, t, i, arr) => (t < arr[best] ? i : best), 0);
console.log('Ambulance la plus proche :', ambulances[fastestIdx].id);import requests
ambulances = [
{'id': 'A-01', 'lat': 36.8280, 'lng': 10.2100},
{'id': 'A-02', 'lat': 36.8450, 'lng': 10.1850},
{'id': 'A-03', 'lat': 36.8094, 'lng': 10.1400},
]
patient = {'lat': 36.8000, 'lng': 10.1815}
res = requests.post(
'https://api.tmaps.tn/distance-matrix',
params={'api_key': 'YOUR_API_KEY'},
json={
'origins': [{'lat': a['lat'], 'lng': a['lng']} for a in ambulances],
'destinations': [patient],
'profile': 'driving',
},
)
durations = res.json()['durations']
fastest = min(range(len(durations)), key=lambda i: durations[i][0])
print('Plus proche :', ambulances[fastest]['id']){
"durations": [
[320],
[180],
[420]
],
"distances": [
[3120],
[1840],
[4250]
],
"origins": [
{ "lat": 36.8280, "lng": 10.2100 },
{ "lat": 36.8450, "lng": 10.1850 },
{ "lat": 36.8094, "lng": 10.1400 }
],
"destinations": [
{ "lat": 36.8000, "lng": 10.1815 }
]
}durations[i][j] = durée en secondes depuis origins[i] jusqu’à destinations[j].distances[i][j] = distance en mètres sur la même paire.origins et destinations sont renvoyés dans le même ordre que la requête, pour faciliter les corrélations côté client.Symétrie
Pour une matrice carrée (mêmes points en origines et destinations), durations[i][i] = 0 et la matrice peut être asymétrique en environnement urbain à cause des sens uniques.
| Statut | Cause |
|---|---|
400 | origins ou destinations manquant, ou plus de 25 points dans l’un des deux |
401 | api_key manquant ou révoqué |
403 | Domaine non autorisé |
404 | Au moins une coordonnée hors couverture |
Voir Codes d’erreur pour la liste complète.
Générez une image PNG d'une carte centrée sur un point, avec markers, polylines et polygones — idéal pour emails, vignettes ou rapports PDF.
L’endpoint Static Maps renvoie une image PNG d’une carte TMaps, centrée sur un point ou calée sur une bbox, avec des overlays (markers, polylines, polygones). Parfait pour :
https://api.tmaps.tn/maps/static?center=lat,lng&zoom=...&size=WxH&api_key=YOUR_API_KEYCadrage (un seul groupe au choix)
| Param | Type | Requis | Défaut | Description |
|---|---|---|---|---|
center | string | — | — | Centre de la carte lat,lng. À combiner avec zoom. |
zoom | integer | — | — | Niveau de zoom (0 → 18). Requis avec center. |
bbox | string | — | — | Boîte englobante minLng,minLat,maxLng,maxLat. La carte ajuste automatiquement le zoom pour englober la bbox. |
Image
| Param | Type | Requis | Défaut | Description |
|---|---|---|---|---|
size | string | oui | — | Dimensions au format WxH en pixels (ex. 800x600). Max 1280 × 1280. |
style | string | — | streets | Style cartographique : streets, dark, terrain, sunny. |
format | string | — | png | Format de retour. Seul png est supporté pour le moment. |
Overlays (optionnels, peuvent être répétés)
| Param | Type | Requis | Défaut | Description |
|---|---|---|---|---|
marker | string | — | — | Un marker, format lat,lng|color|label (ex. 36.8,10.18|red|A). Répétable. |
path | string | — | — | Polyline encodée Google avec options de style — weight:4|color:0x0066ff|enc:abc.... Répétable. |
polygon | string | — | — | Polygone GeoJSON encodé URL ou suite lat,lng|lat,lng|.... Répétable. |
Auth
| Param | Type | Requis | Défaut | Description |
|---|---|---|---|---|
api_key | string | oui | — | Votre clé API TMaps. |
https://api.tmaps.tn/maps/static
?center=36.8528,10.3261
&zoom=15
&size=800x500
&style=streets
&marker=36.8528,10.3261|red|H
&api_key=YOUR_API_KEY<img
src="https://api.tmaps.tn/maps/static?center=36.8528,10.3261&zoom=15&size=800x500&marker=36.8528,10.3261|red|H&api_key=YOUR_API_KEY"
alt="Carte de la propriété"
width="800"
height="500"
/>const url = new URL('https://api.tmaps.tn/maps/static');
url.searchParams.set('center', '36.8528,10.3261');
url.searchParams.set('zoom', '15');
url.searchParams.set('size', '800x500');
url.searchParams.set('style', 'streets');
url.searchParams.append('marker', '36.8528,10.3261|red|H');
url.searchParams.set('api_key', 'YOUR_API_KEY');
document.querySelector('#map-thumbnail').src = url.toString();// Récupère la polyline depuis l'API Direction
const direction = await fetch(
'https://api.tmaps.tn/routing/direction?from=36.8002,10.1815&to=36.8528,10.3261&api_key=YOUR_API_KEY'
).then((r) => r.json());
const url = new URL('https://api.tmaps.tn/maps/static');
url.searchParams.set('size', '1024x600');
url.searchParams.set('style', 'streets');
url.searchParams.append('marker', '36.8002,10.1815|blue|A');
url.searchParams.append('marker', '36.8528,10.3261|red|B');
url.searchParams.append('path', `weight:5|color:0x0066ff|enc:${direction.geometry}`);
url.searchParams.set('api_key', 'YOUR_API_KEY');
document.querySelector('#trip-thumbnail').src = url.toString();red, blue, green, orange, purple, black, white) ou code hex sans # (0xff5500).&marker=36.8002,10.1815|red|A
&marker=36.8528,10.3261|0x0066ff|B
&marker=36.8094,10.1400|greenCache CDN
Les images statiques sont identifiables par leur URL : mettez-les en cache via votre CDN (Cloudflare, BunnyCDN…) pour éviter de re-générer plusieurs fois la même tuile et réduire votre consommation TMaps.
| Statut | Cause |
|---|---|
400 | size au-delà de la limite, paramètres de cadrage incohérents |
401 | api_key manquant ou révoqué |
403 | Domaine non autorisé |
Voir Codes d’erreur pour la liste complète.
Liste complète des codes HTTP renvoyés par l'API TMaps, avec leur signification, leur cause typique et le format du body de réponse.
Toutes les erreurs renvoyées par l'API TMaps suivent un format JSON commun et utilisent les codes HTTP standard. Cette page liste les codes que vous pouvez rencontrer et leur signification.
Toute réponse d'erreur a un body JSON minimal, encodé en UTF-8 :
{
"error": "missing api_key"
} Le champ error contient un message court en anglais, exploitable pour le debug. Ce message peut évoluer dans le temps : ne le parsez pas pour piloter votre logique métier — utilisez le code HTTP.
| HTTP | Signification | Cause typique | Body de réponse |
|---|---|---|---|
| 400 | Mauvaise requête | Paramètre obligatoire manquant ou mal formé | {"error":"missing required param: q"} |
| 401 | Clé API invalide | api_key absent, désactivé ou révoqué | {"error":"missing api_key"} |
| 403 | Domaine non autorisé | Origin / Referer absent de la liste blanche, ou requête HTTP | {"error":"domain not authorized"} |
| 404 | Ressource introuvable | Endpoint ou identifiant inexistant | {"error":"not found"} |
| 429 | Trop de requêtes | Pic ponctuel détecté côté infrastructure (pas de quota par défaut) | {"error":"rate limited"} |
| 500 | Erreur serveur | Incident interne — réessayer après quelques secondes | {"error":"internal error"} |
Pas de rate limit applicatif
L'API TMaps n'impose pas de quota ni de rate limit par clé. Le code429 n'apparaît qu'en cas de protection anti-burst au niveau infrastructure (pic ponctuel) — il est rare en usage normal et résolu par un simple retry with backoff. Les codes 401 et 403 sont des erreurs de configuration, pas d'usage : il ne sert à rien de retenter la requête. Vérifiez plutôt :
401 : la clé est-elle bien renseignée ? Active dans la console ?403 : le domaine d'appel est-il dans la liste des domaines autorisés ? Si l'appel est server-side (sans Origin), le 403 ne devrait pas se produire.429).async function tmapsFetch(url, options = {}, retries = 3) {
for (let i = 0; i < retries; i++) {
const res = await fetch(url, options);
// Pas d'erreur → on retourne
if (res.ok) return res.json();
// 4xx (sauf 429) → erreur définitive
if (res.status >= 400 && res.status < 500 && res.status !== 429) {
const body = await res.json().catch(() => ({}));
throw new Error(`TMaps ${res.status} — ${body.error ?? 'unknown'}`);
}
// 429 ou 5xx → backoff exponentiel
await new Promise((r) => setTimeout(r, 2 ** i * 1000));
}
throw new Error('TMaps: max retries reached');
}