0Pricing
AI Agents · Aula

Lidando com respostas e erros de APIs

Análise de respostas JSON, códigos de erro e padrões de tratamento de exceções.

Lidando com respostas e erros de APIs é uma aula grátis de AI Agents no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de AI Agents, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de AI Agents inclui 4 aulas no total.

O objeto de resposta

Cada chamada de requests retorna um objeto de resposta. Ele contém tudo o que o servidor enviou de volta: o código de status, os cabeçalhos e o corpo. Antes de processar o corpo, sempre examine o código de status — uma resposta com status 500 ainda tem um corpo, mas ele não conterá os dados que você queria.

import requests

response = requests.get('https://api.example.com/data')

# Key attributes of the response
print(response.status_code)       # e.g. 200
print(response.headers)           # dict of response headers
print(response.headers.get('Content-Type'))  # 'application/json'
print(response.text)              # raw response body as string
print(response.content)           # raw bytes

Analisando JSON com response.json()

Chame response.json() para analisar automaticamente o corpo da resposta como JSON em um dicionário ou uma lista do Python. Isso equivale a json.loads(response.text), mas também verifica se o Content-Type é apropriado.

Chame .json() somente quando souber que a resposta é realmente JSON — verifique primeiro o cabeçalho Content-Type.

import requests

response = requests.get(
    'https://api.example.com/users/42',
    headers={'Authorization': 'Bearer YOUR_KEY'}
)

# Parse JSON body
user = response.json()

# Access fields safely with .get()
name = user.get('name', 'Unknown')
email = user.get('email', '')
roles = user.get('roles', [])

print(f'User: {name} ({email})')
print(f'Roles: {roles}')

Verificando o código de status antes de analisar

Nunca chame response.json() sem confirmar primeiro que a solicitação foi concluída com sucesso. As respostas de erro (4xx/5xx) geralmente retornam detalhes do erro em JSON — úteis para depuração —, mas não são os dados de que você precisa. Sempre verifique primeiro o status_code.

import requests

response = requests.post(
    'https://api.example.com/tasks',
    json={'title': 'Write report'},
    headers={'Authorization': 'Bearer YOUR_KEY'}
)

if response.status_code == 201:
    task = response.json()
    print('Task created, ID:', task['id'])
elif response.status_code == 400:
    error = response.json()
    print('Validation error:', error.get('message'))
elif response.status_code == 401:
    print('Auth failed — check your token')
else:
    print(f'Unexpected status {response.status_code}: {response.text[:200]}')

raise_for_status() — geração automática de erros

response.raise_for_status() gera automaticamente uma exceção HTTPError se o código de status for 4xx ou 5xx. Essa é uma maneira simples de transformar respostas HTTP inválidas em exceções do Python, permitindo usar try/except em vez de longas cadeias if/elif.

import requests
from requests.exceptions import HTTPError

try:
    response = requests.get(
        'https://api.example.com/users/9999',
        headers={'Authorization': 'Bearer YOUR_KEY'}
    )
    response.raise_for_status()  # raises if status >= 400
    user = response.json()
    print('Found user:', user['name'])

except HTTPError as e:
    print(f'HTTP error: {e.response.status_code}')
    print('Details:', e.response.text[:300])

Lidando com erros de decodificação JSON

Às vezes, uma API retorna uma resposta que não seja JSON quando você espera JSON — uma página de erro do servidor em HTML, um corpo vazio ou um arquivo binário. Chamar response.json() nesses casos gera json.JSONDecodeError. Sempre capture esse erro para evitar falhas silenciosas do agente.

import requests
import json

response = requests.get(
    'https://api.example.com/report',
    headers={'Authorization': 'Bearer YOUR_KEY'}
)

try:
    data = response.json()
except json.JSONDecodeError as e:
    print(f'Response is not valid JSON: {e}')
    print('Content-Type:', response.headers.get('Content-Type'))
    print('First 200 chars:', response.text[:200])
    # Decide: is this an HTML error page? A CSV file?
    data = None

if data is None:
    print('Falling back to text processing')

ConnectionError — problemas de rede

Um ConnectionError ocorre quando seu agente não consegue alcançar o servidor de forma alguma — falha na resolução de DNS, servidor fora do ar ou firewall bloqueando a solicitação. É uma falha no nível da rede, que ocorre antes mesmo de qualquer comunicação HTTP.

Ao contrário de um erro 5xx, essa não é uma resposta do servidor — a conexão nunca aconteceu.

import requests
from requests.exceptions import ConnectionError

try:
    response = requests.get('https://api.example.com/data')
    data = response.json()
except ConnectionError as e:
    print('Cannot reach server. Possible causes:')
    print('- DNS failure (bad hostname)')
    print('- Server is down')
    print('- No internet connection')
    print('- Firewall blocking the port')
    print(f'Error detail: {e}')
    # Consider: queue the request for retry when connectivity returns

Tempo limite — evitando agentes travados

Por padrão, requests espera indefinidamente por uma resposta. Um servidor lento ou travado congelará seu agente indefinidamente. Sempre defina um tempo limite: uma tupla de (connect_timeout, read_timeout) em segundos. Uma exceção Timeout será gerada se o servidor não responder a tempo.

import requests
from requests.exceptions import Timeout

try:
    response = requests.get(
        'https://api.example.com/slow-endpoint',
        headers={'Authorization': 'Bearer YOUR_KEY'},
        timeout=(5, 30)  # 5s to connect, 30s to read
    )
    data = response.json()
except Timeout:
    print('Request timed out after 30 seconds')
    print('Options: retry, use cached result, or alert operator')

Tratamento abrangente de exceções

Em agentes de produção, capture todas as exceções de requests em uma hierarquia consistente. requests.exceptions.RequestException é a classe base de todos os erros de requests — capturá-la oferece uma proteção contra problemas de rede inesperados.

import requests
import json
from requests.exceptions import (
    ConnectionError, Timeout, HTTPError, RequestException
)

def safe_api_call(url, headers):
    try:
        r = requests.get(url, headers=headers, timeout=(5, 30))
        r.raise_for_status()
        return r.json()
    except Timeout:
        print('ERROR: Request timed out')
    except ConnectionError:
        print('ERROR: Cannot reach server')
    except HTTPError as e:
        print(f'ERROR: HTTP {e.response.status_code}')
        try:
            print('API error:', e.response.json().get('message'))
        except json.JSONDecodeError:
            print('Non-JSON error body')
    except RequestException as e:
        print(f'ERROR: Unexpected request error: {e}')
    return None

Registrando respostas para depuração

Quando um agente se comporta de maneira inadequada, você precisa de contexto suficiente para diagnosticá-lo. Registre o método da solicitação, a URL, o código de status e os detalhes relevantes da resposta — mas nunca registre chaves de API. Use o módulo integrado logging do Python em vez de instruções de impressão nos agentes de produção.

import logging
import requests

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('agent.api')

def logged_request(method, url, **kwargs):
    logger.info(f'-> {method.upper()} {url}')
    response = requests.request(method, url, **kwargs)
    logger.info(
        f'<- {response.status_code} '
        f'({len(response.content)} bytes) '
        f'{response.elapsed.total_seconds():.2f}s'
    )
    if response.status_code >= 400:
        logger.error(f'Error body: {response.text[:500]}')
    return response

Lidando com respostas paginadas

Muitas APIs retornam dados em páginas. Seu agente precisa seguir os links de paginação para obter todos os resultados. Procure uma URL next na resposta ou um campo page/cursor e repita o processo até não haver mais páginas.

import requests

def get_all_items(base_url, headers):
    all_items = []
    url = f'{base_url}/items?page=1&limit=100'

    while url:
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        data = response.json()

        all_items.extend(data.get('items', []))

        # Follow 'next' link if present
        url = data.get('next_page_url')  # None stops the loop

        print(f'Fetched {len(all_items)} items so far...')

    print(f'Total: {len(all_items)} items')
    return all_items

Transmitindo respostas grandes

Para respostas grandes (arquivos, saídas longas de IA), use stream=True para evitar carregar toda a resposta na memória de uma só vez. Leia a resposta em blocos. Isso é essencial quando seu agente processa grandes conjuntos de dados ou transmite texto gerado por IA.

import requests

response = requests.get(
    'https://api.example.com/large-report',
    headers={'Authorization': 'Bearer YOUR_KEY'},
    stream=True
)

response.raise_for_status()

# Write streamed content to file
with open('report.json', 'wb') as f:
    for chunk in response.iter_content(chunk_size=8192):
        if chunk:
            f.write(chunk)

print('Download complete')

# For streaming JSON lines (NDJSON):
for line in response.iter_lines():
    if line:
        import json
        record = json.loads(line)
        print(record)

Verificação rápida: raise_for_status

Teste sua compreensão sobre o tratamento de erros nas respostas.

Recapitulação do tratamento de respostas

O tratamento robusto de respostas é o que diferencia um agente frágil de um confiável:

  • Sempre verifique status_code antes de analisar o corpo
  • Use response.json() para analisar a resposta e capture JSONDecodeError se o corpo puder não estar em JSON
  • Use raise_for_status() para transformar erros HTTP em exceções
  • Capture ConnectionError para falhas de rede e Timeout para servidores lentos
  • Sempre defina uma tupla timeout=(connect, read) em todas as solicitações
  • Registre as solicitações e respostas (sem as chaves) para facilitar a depuração

Perguntas Frequentes

A aula “Lidando com respostas e erros de APIs” é grátis?

Sim — o texto completo de “Lidando com respostas e erros de APIs” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de AI Agents, atualize para CoddyKit PRO. O curso de AI Agents inclui 4 aulas no total.

O que vou aprender em “Lidando com respostas e erros de APIs”?

Análise de respostas JSON, códigos de erro e padrões de tratamento de exceções. Você pratica AI Agents com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar AI Agents?

Nenhuma experiência prévia é necessária. AI Agents no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.

Quanto tempo leva a aula “Lidando com respostas e erros de APIs”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de AI Agents?

Sim. Cada aula de AI Agents inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Fundamentos da API REST para desenvolvedores de agentes
  2. Autenticação: chaves de API e OAuth
  3. Lidando com respostas e erros de APIs
  4. Limitação de taxa e lógica de novas tentativas
← Voltar para AI Agents