Python Requests APIs explicado simplesmente (com diagramas e código real)

Python Requests APIs: o essencial em um artigo — código real, diagramas e etapas concretas, extraídos de um curso de 30 lições.

Python Requests APIs explicado simplesmente (com diagramas e código real)

Um guia direto ao ponto: Python Requests APIs dissecado com diagramas, exemplos concretos e comandos testados. Tudo vem de um curso estruturado de 10 capítulos — aqui está o melhor.

tl;dr
  • Introdução e instalação
  • Bases HTTP
  • Usar requests
  • Autenticação
  • Padrões avançados
~$ cat ./parcours.md # Python Requests APIs — 10 capítulos
01
Introdução e instalação
→ O que é uma API REST ?→ Instalar requests e httpx+ 1 mais lições
02
Bases HTTP
→ Os métodos HTTP→ Códigos de status HTTP+ 1 mais lições
03
Usar requests
→ requests.get e post completos→ JSON e serialização+ 2 mais lições
04
Autenticação
→ Chave de API no header ou query→ Basic Auth e Bearer Token+ 1 mais lições
05
Padrões avançados
→ Paginação→ Rate limiting e retry inteligente+ 1 mais lições
06
Assíncrono
→ Por que httpx async→ asyncio + httpx em paralelo+ 1 mais lições
07
APIs públicas úteis
→ GitHub API - repositórios e issues→ OpenWeather e NewsAPI+ 1 mais lições
08
Webhooks e streaming
→ Receber webhooks→ Server-Sent Events (SSE)+ 1 mais lições
🏁
Projeto final (+ 2 capítulos no caminho)
→ Você sai com um projeto concreto e demonstrável

CLI e agendamento cron

Projeto final • argparse • cron • export

NOTEObjetivo — Finalizar o projeto: interface CLI completa, export JSON/CSV e agendamento automático via cron.

CLI com 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

Agendamento 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

Agendamento no Windows (Task Scheduler)

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

Stripe e SendGrid panorama

NOTEObjetivo — Descobrir Stripe (pagamentos) e SendGrid (e-mails), e escolher entre SDK oficial e requests bruto.

Stripe: criar um pagamento (API HTTP bruta)

output
import requests, os

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

# Stripe utiliza Basic Auth com a chave como usuário
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']}")
# O frontend utiliza client_secret para completar o pagamento

Stripe: criar um cliente

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 oficial (recomendado)

output
pip install stripe

import stripe
stripe.api_key = STRIPE_KEY

# Mais pythônico
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 oficial: retry, tipagem, webhooks assinados, chaves de idempotência automáticas
  • requests: útil se não houver SDK, ou para compreender os conceitos
  • Recomendação: SDK oficial para Stripe/Twilio/AWS, requests para APIs customizadas

SendGrid: enviar um e-mail (HTTP bruta)

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 com 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"     # criado no SendGrid
}
requests.post("https://api.sendgrid.com/v3/mail/send",
               json=payload,
               headers={"Authorization": f"Bearer {SENDGRID_KEY}"})

Outros SDKs populares

ServiçoLibDomínio
StripestripePagamentos
TwiliotwilioSMS, voz
SendGridsendgridE-mails transacionais
AWSboto3Todo AWS (S3, SQS, SES...)
OpenAIopenaiGPT, embeddings
Slackslack_sdkMensagens, webhooks

Boa prática: chave de idempotência

output
import uuid

r = requests.post(
    "https://api.stripe.com/v1/charges",
    auth=(STRIPE_KEY, ""),
    headers={"Idempotency-Key": str(uuid.uuid4())},
    data={...}
)
# Em caso de retry, mesma chave = sem dupla cobrança

Basic Auth e Bearer Token

NOTEObjetivo — Compreender HTTP Basic Auth, os Bearer Tokens e JWT.

HTTP Basic Authentication

Identificador + senha codificados em base64 no cabeçalho Authorization.

output
import requests

# requests faz isso automaticamente com auth=
r = requests.get(
    "https://api.example.com/me",
    auth=("alice", "mot_de_passe")
)

# cabeçalho bruto equivalente:
# Authorization: Basic YWxpY2U6bW90X2RlX3Bhc3Nl
output
from requests.auth import HTTPBasicAuth

r = requests.get(url, auth=HTTPBasicAuth("user", "pwd"))
WARNINGLimites
  • A senha é enviada em texto claro (base64 = não é criptografia)
  • HTTPS OBRIGATÓRIO
  • Sem revogação simples
  • Cada vez menos usado em favor do Bearer

Bearer Token

O token (token) é enviado no cabeçalho Authorization: Bearer .... É o padrão moderno (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)

Formato de Bearer mais comum. Três partes separadas por .: header.payload.signature.

output
import jwt   # pip install PyJWT

token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjMifQ.signature"

# Decodificar sem verificar (para debug)
payload = jwt.decode(token, options={"verify_signature": False})
print(payload)
# {'sub': '123', 'exp': 1700000000}

# Decodificar verificando
payload = jwt.decode(token, key="mon_secret", algorithms=["HS256"])

Auth customizada (subclassificar 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

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

Refresh automático do 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

Este artigo cobre os trechos mais úteis — o curso completo Python Requests APIs (10 capítulos, 30 lições, exercícios corrigidos e projeto final) leva você até o fim.

./acceder-au-cours-complet curso gratuito: Vibe Coding

FAQ

Quanto tempo para aprender Python Requests APIs?
Com uma progressão estruturada (10 capítulos, 30 lições curtas e práticas), você atinge um nível operacional em algumas semanas dedicando 30 a 60 minutos por dia. O importante é praticar cada conceito imediatamente.
Precisa de pré-requisitos?
Básicos de informática são suficientes. Se você sabe usar um terminal e ler código simples, está pronto.
Por onde começar concretamente?
Reproduza os comandos deste artigo, depois siga o curso completo Python Requests APIs: ele encadeia as 30 lições em ordem, com exercícios e projeto final.

📬 Você quer receber este tipo de guia toda semana? Inscreva-se gratuitamente — código real, zero enrolação.