Interagir avec des API REST en Python (Requests)
Mise à jour :
Les API REST sont aujourd’hui omniprésentes : services de géolocalisation,
paiements en ligne, données météorologiques, réseaux sociaux… La capacité à
communiquer avec ces interfaces depuis Python est devenue essentielle pour tout
développeur. Qu’il s’agisse d’automatiser des processus métier, de récupérer des
données externes ou d’intégrer des services tiers dans vos applications, les API
REST constituent le pont qui relie votre code au monde extérieur. La
bibliothèque requests
de Python transforme cette communication en une tâche
intuitive et élégante, permettant d’effectuer des requêtes HTTP complexes avec
seulement quelques lignes de code.
Comprendre les bases d’une API REST
Avant d’écrire la moindre ligne de code, il est essentiel de bien comprendre comment fonctionne une API REST. Ces interfaces permettent à des programmes d’échanger des données en s’appuyant sur le protocole HTTP, celui-là même qui fait fonctionner le web.
Ressources et endpoints
Une API REST expose des ressources (utilisateurs, machines, services…) accessibles via des endpoints (URL). Par exemple, l’URL suivante :
https://api.exemple.com/v1/servers
peut renvoyer la liste des machines virtuelles disponibles sur une plateforme.
Méthodes HTTP
Chaque opération est liée à une méthode HTTP spécifique :
- GET : lire des données
- POST : créer une ressource
- PUT : remplacer une ressource existante
- PATCH : modifier partiellement une ressource
- DELETE : supprimer une ressource
Ces méthodes sont utilisées pour décrire l’intention de l’appel.
Structure JSON
La majorité des API REST échangent des données au format JSON, lisible et léger. Exemple de réponse :
{ "id": 42, "name": "webserver-prod", "status": "running"}
Codes de retour HTTP
À chaque appel, l’API renvoie un code de statut qui indique le résultat :
200 OK
: requête réussie201 Created
: ressource créée204 No Content
: suppression réussie, sans contenu400 Bad Request
: syntaxe incorrecte401 Unauthorized
: clé ou jeton manquant/invalide404 Not Found
: ressource introuvable500 Internal Server Error
: erreur côté serveur
Authentification
Pour des raisons de sécurité, la majorité des API nécessitent une clé d’API ou un jeton Bearer :
Authorization: Bearer eyJhbGciOiJIUzI1...
Ces éléments doivent être transmis dans les headers HTTP, et ne jamais être codés en dur dans les scripts.
Plus d’informations sur les API REST
Préparer son environnement Python
Avant de consommer des API REST en Python, il faut configurer un environnement propre, sécurisé et prêt pour l’automatisation. Voici les étapes à suivre.
Créer un environnement virtuel
Créez un environnement virtuel avec venv
pour isoler vos dépendances :
python -m venv venvsource venv/bin/activate
Installer la bibliothèque requests
Le module requests
est la bibliothèque la plus simple et la plus utilisée
pour faire des appels HTTP en Python. Pour l’installer :
pip install requests
Ce module gère les méthodes HTTP, les entêtes, les erreurs, l’encodage JSON, etc.
Créer une structure de script claire
Organisez vos scripts avec une structure modulaire :
mon_script_api/├── main.py├── api_utils.py└── .env
main.py
: point d’entrée du scriptapi_utils.py
: fonctions réutilisables (authentification, requêtes).env
: fichier contenant les clés d’API ou les jetons d’accès
Utiliser un fichier .env
pour les secrets
Pour éviter de stocker des identifiants directement dans le code, stockez-les
dans un fichier .env
:
API_KEY=sk_test_abc123BASE_URL=https://api.exemple.com
Et lisez-les dans votre script avec la bibliothèque python-dotenv
:
pip install python-dotenv
Dans le script :
from dotenv import load_dotenvimport os
load_dotenv()api_key = os.getenv("API_KEY")
Pour éviter de commettre ce fichier dans Git, ajoutez .env
à votre
.gitignore
.
Utiliser la bibliothèque requests
La bibliothèque requests
simplifie les appels HTTP en Python. Voici comment
l’utiliser pour interagir avec une API REST.
Pour apprendre à l’utiliser, nous allons utiliser JSONPlaceholder. C’est une API REST factice gratuite qui simule des endpoints courants.
Lire une ressource avec GET
Pour récupérer une ressource, utilisez la méthode GET
:
import requests
url = "https://jsonplaceholder.typicode.com/todos/1"response = requests.get(url)print(response.json())
Résultat attendu :
{ "userId": 1, "id": 1, "title": "delectus aut autem", "completed": False}
Créer une tâche avec POST
Pour créer une nouvelle ressource, utilisez la méthode POST
:
payload = { "userId": 1, "title": "Créer un playbook Ansible", "completed": False}response = requests.post("https://jsonplaceholder.typicode.com/todos", json=payload)print(response.json())
Même si la création est fictive, l’API renvoie un objet JSON contenant un ID simulé.
{ "userId": 1, "title": "Créer un playbook Ansible", "completed": False, "id": 201}
Modifier une tâche avec PUT
Pour remplacer une ressource existante, utilisez la méthode PUT
:
update = { "userId": 1, "title": "Tâche mise à jour", "completed": True}response = requests.put("https://jsonplaceholder.typicode.com/todos/1", json=update)print(response.json())
Vous devriez obtenir une réponse similaire à celle-ci :
{ "userId": 1, "id": 1, "title": "Tâche mise à jour", "completed": True}
Mise à jour partielle avec PATCH
Pour modifier partiellement une ressource, utilisez la méthode PATCH
:
partial = {"completed": False}response = requests.patch("https://jsonplaceholder.typicode.com/todos/1", json=partial)print(response.json())
La réponse contiendra uniquement les champs modifiés :
{ "userId": 1, "id": 1, "title": "delectus aut autem", "completed": False}
Supprimer une tâche avec DELETE
Pour supprimer une ressource, utilisez la méthode DELETE
:
response = requests.delete("https://jsonplaceholder.typicode.com/todos/1")print(f"Code de statut : {response.status_code}")
En général, l’API renvoie un 204 No Content ou 200 OK sans contenu.
Gérer les erreurs et exceptions
Lorsque vous consommez des API, il est essentiel de gérer les erreurs pour rendre vos scripts robustes, surtout dans un environnement d’infrastructure automatisé. Cela évite que des appels échoués passent inaperçus ou génèrent des comportements inattendus.
Vérifier les codes de statut HTTP
Chaque réponse d’API contient un code de statut HTTP. Utilisez-les pour détecter les erreurs :
response = requests.get("https://jsonplaceholder.typicode.com/todos/1")if response.status_code == 200: print("Succès :", response.json())elif response.status_code == 404: print("Ressource non trouvée.")else: print(f"Erreur : {response.status_code}")
Ou utilisez directement :
if response.ok: # code 2xx
Cela est équivalente à vérifier si le code de statut est dans la plage 2xx.
Lever automatiquement les erreurs
Pour simplifier la détection, utilisez raise_for_status()
:
try: response = requests.get("https://api.exemple.com/data") response.raise_for_status() print(response.json())except requests.exceptions.HTTPError as e: print(f"Erreur HTTP : {e}")
Cette méthode déclenche une exception si le code HTTP n’est pas dans la plage 2xx.
Ici, le code lève une exception HTTPError
si la requête échoue, ce qui permet
de capturer les erreurs réseau ou de statut HTTP sans avoir à vérifier
manuellement le code de statut.
Erreur HTTP : 410 Client Error: Gone for url: https://api.exemple.com/data
Capturer les erreurs réseau
Les problèmes de réseau ou d’URL incorrectes doivent être capturés avec
RequestException
:
try: response = requests.get("https://mauvaise-url") response.raise_for_status()except requests.exceptions.ConnectionError: print("Erreur de connexion")except requests.exceptions.Timeout: print("Délai d’attente dépassé")except requests.exceptions.RequestException as e: print(f"Erreur générale : {e}")
Ce code gère les erreurs de connexion, les délais d’attente et les autres exceptions liées aux requêtes.
Erreur de connexion
Ajouter des délais d’attente (timeout
)
Pour éviter que votre script ne reste bloqué en cas d’API lente :
requests.get("https://jsonplaceholder.typicode.com/todos/1", timeout=5)
Cela déclenche une exception après 5 secondes d’attente.
Journaux d’erreur (logging)
Dans un script d’automatisation, loguez les erreurs au lieu de juste les afficher :
import logginglogging.basicConfig(filename='api.log', level=logging.ERROR)
try: r = requests.get("https://api.exemple.com/data") r.raise_for_status()except requests.exceptions.RequestException as e: logging.error(f"Appel échoué : {e}")
Plus d’informations sur la gestion des erreurs.
Travailler avec des API sécurisées
Lorsqu’on consomme des API REST, la gestion de l’authentification est
primordiale. Elle garantit que seules les entités autorisées peuvent accéder aux
ressources. Python, via requests
, permet de gérer plusieurs types
d’authentification. Voici les modèles les plus courants, du plus simple au plus
avancé.
Authentification HTTP Basic
Le schéma Basic envoie un couple utilisateur:motdepasse
encodé en
Base64 dans un entête HTTP :
Authorization: Basic base64(utilisateur:motdepasse)
Python gère automatiquement cette conversion via le module requests.auth
:
from requests.auth import HTTPBasicAuthimport requests
auth = HTTPBasicAuth("admin", "motdepasse")response = requests.get("https://api.exemple.com/serveurs", auth=auth)
Cela génère automatiquement le header :
Authorization: Basic YWRtaW46bW90ZGVwYXNzZQ==
⚠️ Cette méthode doit toujours être utilisée avec HTTPS, car l’encodage Base64 n’est pas du chiffrement.
Authentification par clé API (API Key)
De nombreuses APIs utilisent une clé d’authentification unique, transmise de deux façons :
Dans les en-têtes HTTP
headers = { "x-api-key": "sk_test_ABC123"}response = requests.get("https://api.exemple.com/instances", headers=headers)
En paramètre de requête
params = { "api_key": "sk_test_ABC123"}response = requests.get("https://api.exemple.com/instances", params=params)
Ce type d’authentification est simple mais sensible à l’exposition de la clé. Elle donne un accès complet aux endpoints autorisés.
Jeton Bearer (OAuth2, JWT)
La méthode Bearer consiste à transmettre un jeton d’accès temporaire dans l’en-tête HTTP :
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
En Python :
headers = { "Authorization": "Bearer VOTRE_JETON", "Accept": "application/json"}response = requests.get("https://api.exemple.com/vms", headers=headers)
Ce jeton est souvent obtenu via un login initial ou une authentification OAuth2, et expire généralement après un certain temps.
OAuth2 — Jeton via identifiants client
De nombreuses APIs (GitLab, Azure, etc.) imposent un échange initial pour
obtenir un jeton d’accès temporaire, en envoyant un client_id
et un
client_secret
:
url = "https://auth.exemple.com/oauth/token"data = { "grant_type": "client_credentials", "client_id": "votre_id", "client_secret": "votre_secret"}
response = requests.post(url, data=data)access_token = response.json()["access_token"]
Puis utilisation du jeton :
headers = {"Authorization": f"Bearer {access_token}"}requests.get("https://api.exemple.com/data", headers=headers)
5. Sessions persistantes avec requests.Session
Pour éviter de dupliquer les headers d’authentification sur plusieurs appels :
session = requests.Session()session.headers.update({ "Authorization": "Bearer VOTRE_JETON", "Accept": "application/json"})
response = session.get("https://api.exemple.com/monitoring")
Cela améliore la lisibilité et la maintenabilité du code dans les scripts plus longs.
Bonnes pratiques pour sécuriser l’authentification API
Utiliser une authentification sécurisée dans vos scripts Python ne suffit pas : il faut également adopter des bonnes pratiques pour éviter les fuites d’informations sensibles, protéger vos infrastructures, et garantir la maintenabilité de vos scripts d’automatisation.
Ne jamais coder en dur une clé ou un mot de passe
Évitez d’insérer vos API keys, tokens, ou mots de passe directement dans le script. Exemple à éviter absolument :
# Mauvais exempleheaders = {"Authorization": "Bearer sk_live_tres_secret"}
En cas de fuite (GitHub, partage de fichier…), cela donne un accès direct à vos ressources.
Utiliser un fichier .env
pour stocker les secrets
Créez un fichier .env
:
API_KEY=sk_prod_xxxxxxBEARER_TOKEN=eyJhbGciOiJIUzI1...
Ajoutez ensuite ce fichier à .gitignore
:
.env
Dans votre script Python, chargez les variables avec python-dotenv
:
pip install python-dotenv
import osfrom dotenv import load_dotenv
load_dotenv()api_key = os.getenv("API_KEY")headers = {"x-api-key": api_key}
Chiffrer les échanges (HTTPS obligatoire)
Tous les appels API doivent être faits sur des URLs HTTPS. Le chiffrement TLS :
- Protège les données en transit (auth, payload)
- Évite les attaques de type man-in-the-middle
Stocker les logs d’erreurs sans exposer les secrets
Lorsque vous tracez des appels API échoués, n’incluez jamais les clés ou tokens dans les logs :
import logging
try: response = requests.get("https://api.exemple.com/infra") response.raise_for_status()except requests.exceptions.RequestException as e: logging.error(f"Erreur API : {e}")
Revoir et sécuriser les dépôts Git
- Toujours ajouter
.env
à.gitignore
- Scanner votre historique Git avec
truffleHog
ougitleaks
pour détecter les fuites - Utiliser GitHub Secrets, GitLab CI/CD Variables ou Vault pour injecter les valeurs dynamiquement
Contrôle de connaissances
Pourquoi ce contrôle ?
Cet contrôle va vous permettre de valider vos connaissances sur le sujet abordé dans le guide. Il comporte des QCM, des questions vrai/faux et des réponses ouvertes à un mot.
🕒 Le chronomètre commence dès que vous cliquez sur Démarrer le test. Vous devrez terminer l’examen avant la fin du temps imparti.
🎯 Pour réussir, vous devez obtenir au moins 80% de bonnes réponses.
💡 Je ne fournis pas directement les réponses aux questions. Cependant, si certaines sont complexes, des pistes d’explication pourront être proposées dans le guide ou après l’examen.
Bonne chance ! 🚀
Conclusion
Consommer des API REST en Python est une compétence indispensable pour
automatiser et intégrer vos outils d’infrastructure. Grâce à la simplicité de
requests
, il est possible de piloter des services distants de manière fiable
et sécurisée. En appliquant les bonnes pratiques d’authentification et de
gestion des erreurs, vos scripts deviennent des briques robustes au cœur de vos
workflows DevOps.