Python Requests APIs expliqué simplement (avec schémas et vrai code)

Python Requests APIs : l'essentiel en un article — vrai code, schémas et étapes concrètes, extraits d'un cours de 30 leçons.

Python Requests APIs expliqué simplement (avec schémas et vrai code)

Un guide qui va droit au but : Python Requests APIs décortiqué avec des schémas, des exemples concrets et des commandes testées. Tout vient d'un cours structuré de 10 chapitres — en voici le meilleur.

tl;dr
  • Introduction et installation
  • Bases HTTP
  • Utiliser requests
  • Authentification
  • Patterns avances
~$ cat ./parcours.md # Python Requests APIs — 10 chapitres
01
Introduction et installation
→ Qu'est-ce qu'une API REST ?→ Installer requests et httpx+ 1 autres leçons
02
Bases HTTP
→ Les methodes HTTP→ Status codes HTTP+ 1 autres leçons
03
Utiliser requests
→ requests.get et post complets→ JSON et serialisation+ 2 autres leçons
04
Authentification
→ API Key dans header ou query→ Basic Auth et Bearer Token+ 1 autres leçons
05
Patterns avancés
→ Pagination→ Rate limiting et retry intelligent+ 1 autres leçons
06
Asynchrone
→ Pourquoi httpx async→ asyncio + httpx en parallele+ 1 autres leçons
07
APIs publiques utiles
→ GitHub API - depots et issues→ OpenWeather et NewsAPI+ 1 autres leçons
08
Webhooks et streaming
→ Recevoir des webhooks→ Server-Sent Events (SSE)+ 1 autres leçons
🏁
Projet final (+ 2 chapitres en chemin)
→ Tu repars avec un projet concret et démontrable

CLI et planification cron

Projet final • argparse • cron • export

NOTEObjectif — Finaliser le projet : interface CLI complete, export JSON/CSV et planification automatique via cron.

CLI avec argparse

output
# app/cli.py
import argparse, asyncio, json, sqlite3, sys
from . import aggregator, config

def cmd_fetch(args):
    inserted = asyncio.run(aggregator.run_once())
    print(f"Nouveaux articles : {inserted}")

def cmd_list(args):
    conn = sqlite3.connect(config.DB_PATH)
    conn.row_factory = sqlite3.Row
    
    query = "SELECT * FROM articles WHERE 1=1"
    params = []
    if args.source:
        query += " AND source = ?"
        params.append(args.source)
    if args.search:
        query += " AND (title LIKE ? OR summary LIKE ?)"
        params.extend([f"%{args.search}%"] * 2)
    query += f" ORDER BY published_at DESC LIMIT {args.limit}"
    
    for row in conn.execute(query, params):
        print(f"[{row['source']}] {row['published_at'][:10]}")
        print(f"  {row['title']}")
        print(f"  -> {row['url']}\n")

def cmd_export(args):
    conn = sqlite3.connect(config.DB_PATH)
    conn.row_factory = sqlite3.Row
    rows = [dict(r) for r in conn.execute("SELECT * FROM articles")]
    
    if args.format == "json":
        with open(args.output, "w", encoding="utf-8") as f:
            json.dump(rows, f, ensure_ascii=False, indent=2)
    elif args.format == "csv":
        import csv
        with open(args.output, "w", newline="", encoding="utf-8") as f:
            w = csv.DictWriter(f, fieldnames=rows[0].keys())
            w.writeheader()
            w.writerows(rows)
    
    print(f"{len(rows)} articles -> {args.output}")

def main():
    p = argparse.ArgumentParser(prog="news", description="Agregateur de news")
    sub = p.add_subparsers(dest="cmd", required=True)
    
    sub.add_parser("fetch", help="Recuperer les articles").set_defaults(func=cmd_fetch)
    
    pl = sub.add_parser("list", help="Lister")
    pl.add_argument("--source", help="Filtrer par source")
    pl.add_argument("--search", help="Rechercher")
    pl.add_argument("--limit", type=int, default=20)
    pl.set_defaults(func=cmd_list)
    
    pe = sub.add_parser("export", help="Exporter")
    pe.add_argument("--format", choices=["json", "csv"], default="json")
    pe.add_argument("--output", default="export.json")
    pe.set_defaults(func=cmd_export)
    
    args = p.parse_args()
    args.func(args)

if __name__ == "__main__":
    main()

Usage

output
python -m app.cli fetch
python -m app.cli list --limit 10
python -m app.cli list --source hackernews
python -m app.cli list --search "python"
python -m app.cli export --format csv --output news.csv

Console entry point

output
# pyproject.toml
[project.scripts]
news = "app.cli:main"
output
pip install -e .
news fetch
news list --limit 5

Planification cron (Linux/Mac)

output
crontab -e

# Toutes les 30 minutes
*/30 * * * * cd /home/user/news_agg && \
  /home/user/.venv/bin/news fetch >> logs/news.log 2>&1

Planification sur Windows (Task Scheduler)

output
# PowerShell
schtasks /Create /SC MINUTE /MO 30 /TN "NewsAgg" /TR "C:\path\to\python.exe -m app.cli fetch"

Stripe et SendGrid panorama

NOTEObjectif — Decouvrir Stripe (paiements) et SendGrid (emails), et choisir entre SDK officiel et requests brut.

Stripe : creer un paiement (API HTTP brute)

output
import requests, os

STRIPE_KEY = os.getenv("STRIPE_SECRET_KEY")   # sk_test_...

# Stripe utilise Basic Auth avec la cle comme user
r = requests.post(
    "https://api.stripe.com/v1/payment_intents",
    auth=(STRIPE_KEY, ""),
    data={
        "amount": 2000,           # 20.00 EUR
        "currency": "eur",
        "payment_method_types[]": "card",
        "description": "Commande #1234"
    },
    timeout=10
)
r.raise_for_status()
intent = r.json()
print(f"client_secret : {intent['client_secret']}")
# Le frontend utilise client_secret pour completer le paiement

Stripe : creer un client

output
r = requests.post("https://api.stripe.com/v1/customers",
                   auth=(STRIPE_KEY, ""),
                   data={"email": "alice@example.com",
                         "name": "Alice Dupont"})
customer = r.json()
print(customer["id"])   # cus_xxx

SDK Stripe officiel (recommande)

output
pip install stripe

import stripe
stripe.api_key = STRIPE_KEY

# Plus pythonique
intent = stripe.PaymentIntent.create(
    amount=2000,
    currency="eur",
    payment_method_types=["card"],
    description="Commande #1234"
)
print(intent.id)
print(intent.client_secret)
TIPSDK vs requests
  • SDK officiel : retry, typage, webhooks signes, idempotency keys auto
  • requests : utile si pas de SDK, ou pour comprendre les concepts
  • Recommandation : SDK officiel pour Stripe/Twilio/AWS, requests pour APIs custom

SendGrid : envoyer un email (HTTP brute)

output
SENDGRID_KEY = os.getenv("SENDGRID_API_KEY")

payload = {
    "personalizations": [{
        "to": [{"email": "destinataire@example.com"}],
        "subject": "Hello depuis Python"
    }],
    "from": {"email": "contact@mondomaine.com", "name": "Mon App"},
    "content": [{
        "type": "text/html",
        "value": "<h1>Bonjour !</h1><p>Envoye via API.</p>"
    }]
}

r = requests.post(
    "https://api.sendgrid.com/v3/mail/send",
    json=payload,
    headers={"Authorization": f"Bearer {SENDGRID_KEY}"},
    timeout=10
)
print(r.status_code)   # 202 Accepted

SendGrid avec template

output
payload = {
    "personalizations": [{
        "to": [{"email": "alice@example.com"}],
        "dynamic_template_data": {
            "name": "Alice",
            "order_id": "#1234",
            "total": "29.99 EUR"
        }
    }],
    "from": {"email": "orders@mondomaine.com"},
    "template_id": "d-xxxxx"     # cree dans SendGrid
}
requests.post("https://api.sendgrid.com/v3/mail/send",
               json=payload,
               headers={"Authorization": f"Bearer {SENDGRID_KEY}"})

Autres SDKs populaires

ServiceLibDomaine
StripestripePaiements
TwiliotwilioSMS, voix
SendGridsendgridEmails transactionnels
AWSboto3Tout AWS (S3, SQS, SES...)
OpenAIopenaiGPT, embeddings
Slackslack_sdkMessages, webhooks

Bonne pratique : idempotency key

output
import uuid

r = requests.post(
    "https://api.stripe.com/v1/charges",
    auth=(STRIPE_KEY, ""),
    headers={"Idempotency-Key": str(uuid.uuid4())},
    data={...}
)
# En cas de retry, meme key = pas de double facturation

Basic Auth et Bearer Token

NOTEObjectif — Comprendre HTTP Basic Auth, les Bearer Tokens et JWT.

HTTP Basic Authentication

Identifiant + mot de passe encodes en base64 dans le header Authorization.

output
import requests

# requests le fait automatiquement avec auth=
r = requests.get(
    "https://api.example.com/me",
    auth=("alice", "mot_de_passe")
)

# equivalent header brut :
# Authorization: Basic YWxpY2U6bW90X2RlX3Bhc3Nl
output
from requests.auth import HTTPBasicAuth

r = requests.get(url, auth=HTTPBasicAuth("user", "pwd"))
WARNINGLimites
  • Le mot de passe est envoye en clair (base64 = pas du chiffrement)
  • HTTPS OBLIGATOIRE
  • Pas de revocation simple
  • De moins en moins utilise au profit du Bearer

Bearer Token

Le token (jeton) est envoye dans le header Authorization: Bearer .... C'est le standard moderne (OAuth, JWT...).

output
TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

r = requests.get(
    "https://api.github.com/user",
    headers={"Authorization": f"Bearer {TOKEN}"}
)

print(r.json())

JWT (JSON Web Token)

Format de Bearer le plus repandu. Trois parties separees par . : header.payload.signature.

output
import jwt   # pip install PyJWT

token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjMifQ.signature"

# Decoder sans verifier (pour debug)
payload = jwt.decode(token, options={"verify_signature": False})
print(payload)
# {'sub': '123', 'exp': 1700000000}

# Decoder en verifiant
payload = jwt.decode(token, key="mon_secret", algorithms=["HS256"])

Auth custom (sous-classer AuthBase)

output
from requests.auth import AuthBase

class BearerAuth(AuthBase):
    def __init__(self, token):
        self.token = token
    def __call__(self, req):
        req.headers["Authorization"] = f"Bearer {self.token}"
        return req

# Usage
r = requests.get(url, auth=BearerAuth(TOKEN))

Refresh automatique du token

output
import time

class TokenManager:
    def __init__(self, client_id, client_secret):
        self.client_id = client_id
        self.client_secret = client_secret
        self._token = None
        self._expires_at = 0
    
    def get_token(self) -> str:
        if not self._token or time.time() > self._expires_at - 60:
            self._refresh()
        return self._token
    
    def _refresh(self):
        r = requests.post("https://auth.example.com/token", data={
            "grant_type": "client_credentials",
            "client_id": self.client_id,
            "client_secret": self.client_secret
        })
        r.raise_for_status()
        d = r.json()
        self._token = d["access_token"]
        self._expires_at = time.time() + d["expires_in"]

mgr = TokenManager(...)
r = requests.get(url, headers={"Authorization": f"Bearer {mgr.get_token()}"})
va-plus-loin

Cet article couvre les extraits les plus utiles — le cours complet Python Requests APIs (10 chapitres, 30 leçons, exercices corrigés et projet final) t'emmène jusqu'au bout.

./acceder-au-cours-complet cours gratuit : Vibe Coding

FAQ

Combien de temps pour apprendre Python Requests APIs ?
Avec une progression structurée (10 chapitres, 30 leçons courtes et pratiques), on atteint un niveau opérationnel en quelques semaines à raison de 30 à 60 minutes par jour. L'important est de pratiquer chaque notion immédiatement.
Faut-il des prérequis ?
Des bases en informatique suffisent. Si tu sais utiliser un terminal et lire du code simple, tu es prêt.
Par où commencer concrètement ?
Reproduis les commandes de cet article, puis suis le cours complet Python Requests APIs : il enchaîne les 30 leçons dans l'ordre, avec exercices et projet final.

📬 Tu veux recevoir ce type de guide chaque semaine ? Abonne-toi gratuitement — code réel, zéro blabla.