RESTClient est la brique de bas niveau de dlt pour l’extraction par API. Il encapsule la bibliothèque requests de Python et y ajoute la pagination, l’authentification et la gestion des reprises. On instancie un client avec une configuration, puis on utilise paginate() pour itérer sur les réponses de l’API au sein d’une fonction de resource dlt.
Instanciation
from dlt.sources.helpers.rest_client import RESTClientfrom dlt.sources.helpers.rest_client.paginators import OffsetPaginator
client = RESTClient( base_url="https://api.example.com/v1", headers={"X-API-Version": "2024-01"}, paginator=OffsetPaginator(limit=100))Les paramètres clés :
base_url: L’URL racine de l’API, partagée entre tous les endpoints que le client interrogeheaders: En-têtes par défaut envoyés avec chaque requête — épingles de version d’API, déclarations de type de contenu, tout ce qui doit figurer dans toutes les requêtesauth: Un objet de stratégie d’authentification (voir dlt Authentication Patterns)paginator: Comment gérer les réponses multi-pages (voir dlt Pagination Patterns)data_selector: Chemin JSONPath vers les données réelles dans la réponse — utile lorsque le payload est imbriqué comme{"result": {"items": [...]}}
La méthode paginate()
paginate() est ce qui fait le gros du travail. Passez-lui un chemin d’endpoint, et elle produit des pages de données jusqu’à ce que l’API signale qu’il n’y en a plus :
@dlt.resource(write_disposition="merge", primary_key="id")def customers(): for page in client.paginate("/customers"): yield pageChaque itération dans la boucle donne la réponse JSON parsée pour une page. Le paginator gère toute la mécanique de suivi des liens page suivante, d’incrémentation des offsets ou d’avancement des curseurs — il suffit de consommer les pages.
Il est possible de passer des paramètres par requête directement à paginate() :
@dlt.resource(write_disposition="merge", primary_key="id")def orders(updated_since=dlt.sources.incremental("updated_at", initial_value="2024-01-01")): params = {"updated_after": updated_since.last_value} for page in client.paginate("/orders", params=params): yield pageCela rend RESTClient composable avec le chargement incrémental de dlt — on passe la valeur du curseur comme paramètre de requête et le paginator gère tout le reste.
Gestion des erreurs et résilience
Les API échouent. Les limites de taux se déclenchent à 3h du matin. Les réseaux se coupent en milieu de synchronisation. dlt gère automatiquement les modes d’échec courants, éliminant la nécessité d’écrire soi-même la logique de retry.
Pour les réponses HTTP 429 (limite de taux), dlt respecte les en-têtes Retry-After et implémente un backoff exponentiel. Par défaut, jusqu’à 5 tentatives. Le comportement de backoff peut être ajusté :
client = RESTClient( base_url="https://api.example.com", request_backoff_factor=2, # Multiplicateur de backoff exponentiel request_max_retry_delay=300 # Nombre maximum de secondes entre les retries)Avec request_backoff_factor=2, les retries se produisent à 2s, 4s, 8s, 16s, 32s (plafonnés à request_max_retry_delay). Pour les API avec des limites de taux agressives, définir request_max_retry_delay=300 donne un plafond de 5 minutes avant abandon.
Ce comportement de retry automatique rend les pipelines RESTClient résilients aux échecs transitoires sans code supplémentaire. Les échecs permanents — 401 Unauthorized, 404 Not Found sur un endpoint incorrect — remontent immédiatement sans gaspiller de tentatives.
Construction de resources dlt
Les instances RESTClient sont conçues pour être partagées entre plusieurs resources dans la même source :
@dlt.sourcedef my_api_source(): client = RESTClient( base_url="https://api.example.com/v1", auth=BearerTokenAuth(token=dlt.secrets["api_token"]), paginator=JSONLinkPaginator(next_url_path="next") )
@dlt.resource(write_disposition="merge", primary_key="id") def customers(): for page in client.paginate("/customers"): yield page
@dlt.resource(write_disposition="merge", primary_key="id") def orders(): for page in client.paginate("/orders"): yield page
return customers, ordersLe client porte la configuration partagée — URL de base, authentification, en-têtes par défaut — tandis que chaque fonction de resource définit quel endpoint interroger et comment produire les données. Ce pattern centralise la gestion des identifiants et évite de répéter la configuration dans chaque resource.
Quand RESTClient se distingue
La flexibilité de RESTClient est payante lorsque l’API fait quelque chose de non standard : un flux d’authentification personnalisé, un schéma de pagination nécessitant une logique avec état, ou un traitement des réponses nécessitant une production conditionnelle basée sur le contenu de la réponse. Dans les cas où la REST API Source atteint ses limites de configuration, RESTClient est la porte de sortie qui maintient l’intégration dans l’écosystème dlt plutôt que de forcer une implémentation entièrement personnalisée.