Manejo de errores
Códigos de error HTTP
| Código | Significado | Causa común | Acción recomendada |
|---|---|---|---|
| 400 | Bad Request | Falta el campo requerido medical_note o formato de petición inválido | Asegurar que el campo medical_note está proporcionado (requerido) |
| 401 | Unauthorized | Token inválido o expirado | Verifique su token Bearer y que esté activo |
| 413 | Payload Too Large | medical_note excede 50KB o pdf_file excede 5MB decodificado | Reducir tamaño de entrada o dividir contenido |
| 422 | Unprocessable Entity | Estructura PDF inválida, datos base64 malformados, mime_type inválido | Validar estructura y codificación del archivo PDF |
| 429 | Too Many Requests | Límite de velocidad excedido | Espera y reintenta con backoff exponencial |
| 500 | Internal Server Error | Error inesperado del servidor, problemas de base de datos, mala configuración | Reintenta con backoff exponencial; si persiste, reporta el run_id |
| 503 | Service Unavailable | Servicio de IA temporalmente no disponible | Reintenta después de unos segundos |
| 504 | Gateway Timeout | La petición excedió el límite de procesamiento de 10 minutos | Reducir tamaño de entrada o dividir contenido |
Formato de respuestas de error
Todos los errores siguen esta estructura consistente:{
"success": false,
"error": "Bad Request",
"details": "medical_note es requerido"
}
Campos de error
| Campo | Descripción |
|---|---|
success | Siempre false para respuestas de error |
error | Nombre/tipo de error (ej: “Bad Request”, “Unauthorized”) |
details | Mensaje de error detallado explicando qué salió mal |
Estrategia de reintentos
¿Cuándo reintentar?
Sí, reintentar:- Errores 5xx (500, 502, 503, 504)
- Error 429 (Too Many Requests)
- Errores de red/timeout
- Errores 4xx excepto 429 (son errores de cliente)
- Error 401 (token inválido)
- Error 422 (esquema inválido)
Backoff exponencial
Intento 1: inmediato
Intento 2: espera 1 segundo
Intento 3: espera 2 segundos
Intento 4: espera 4 segundos
Intento 5: espera 8 segundos
...
Implementación
import time
import requests
from requests.exceptions import RequestException
def codify_with_retry(payload, max_retries=3):
"""Llama a la API Codify con reintentos exponenciales"""
url = "https://{tu-endpoint}/v1/codify"
headers = {
"Authorization": "Bearer TU_TOKEN",
"Content-Type": "application/json"
}
for attempt in range(max_retries):
try:
response = requests.post(
url=url,
json=payload,
headers=headers,
timeout=600 # Timeout de 10 minutos para Codify
)
# Si es 429 o 5xx, reintentar
if response.status_code in [429, 500, 502, 503, 504]:
if attempt < max_retries - 1:
wait_time = 2 ** attempt
print(f"Reintentando en {wait_time}s...")
time.sleep(wait_time)
continue
# Para otros errores, lanzar excepción
response.raise_for_status()
return response.json()
except RequestException as e:
if attempt < max_retries - 1:
wait_time = 2 ** attempt
print(f"Error de red, reintentando en {wait_time}s...")
time.sleep(wait_time)
else:
raise
raise Exception("Máximo de reintentos alcanzado")
# Uso
try:
result = codify_with_retry({
"medical_note": "Paciente con Diabetes tipo 2...",
"model": "balanced"
})
print(f"Éxito! Códigos: {len(result['final_code_assessments'])}")
except Exception as e:
print(f"Error: {e}")
async function codifyWithRetry(payload, maxRetries = 3) {
const url = 'https://{tu-endpoint}/v1/codify';
const headers = {
'Authorization': 'Bearer TU_TOKEN',
'Content-Type': 'application/json'
};
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await axios.post(url, payload, {
headers,
timeout: 600000 // Timeout de 10 minutos para Codify
});
return response.data;
} catch (error) {
const status = error.response?.status;
// Reintentar en 429 y 5xx
if ([429, 500, 502, 503, 504].includes(status)) {
if (attempt < maxRetries - 1) {
const waitTime = Math.pow(2, attempt) * 1000;
console.log(`Reintentando en ${waitTime/1000}s...`);
await new Promise(resolve => setTimeout(resolve, waitTime));
continue;
}
}
// Para otros errores, lanzar
throw error;
}
}
throw new Error('Máximo de reintentos alcanzado');
}
// Uso
try {
const result = await codifyWithRetry({
medical_note: 'Paciente con Diabetes tipo 2...',
model: 'balanced'
});
console.log(`Éxito! Códigos: ${result.final_code_assessments.length}`);
} catch (error) {
console.error('Error:', error.response?.data || error.message);
}
Seguimiento y auditoría
Uso de run_id para depuración
Cada respuesta incluye unrun_id único que debe almacenar para seguimiento y depuración:
def save_codification_result(patient_id, result):
"""Guardar resultado de codificación con run_id para seguimiento"""
database.insert({
'patient_id': patient_id,
'run_id': result['run_id'],
'codes': result['final_code_assessments'],
'discarded_codes': result['discarded_code_assessments'],
'timestamp': datetime.now(),
'processed': True
})
print(f"✅ Codificación guardada (run_id: {result['run_id']})")
return result['run_id']
# Uso
result = codify_with_retry({"medical_note": "..."})
run_id = save_codification_result("pt_456", result)
Deduplicación por hash de contenido
Para evitar procesar la misma nota múltiples veces, use hash de contenido:import hashlib
import json
def get_content_hash(medical_note):
"""Generar hash del contenido de la nota médica"""
return hashlib.sha256(medical_note.encode()).hexdigest()
def codify_with_deduplication(medical_note):
"""Procesar nota solo si no ha sido procesada anteriormente"""
content_hash = get_content_hash(medical_note)
# Verificar si ya se procesó
existing = database.query(
"SELECT * FROM codifications WHERE content_hash = ?",
content_hash
)
if existing:
print(f"✅ Ya procesado (run_id: {existing['run_id']})")
return existing['result']
# Procesar nueva nota
result = codify_with_retry({"medical_note": medical_note})
# Guardar con hash
database.insert({
'content_hash': content_hash,
'run_id': result['run_id'],
'result': json.dumps(result),
'processed_at': datetime.now()
})
return result
Headers opcionales de seguimiento
Use los headersdoctor y patient para mejorar las pistas de auditoría:
def codify_with_tracking(medical_note, doctor_id, patient_id):
"""Codificar con información completa de seguimiento"""
url = "https://{tu-endpoint}/v1/codify"
headers = {
"Authorization": "Bearer TU_TOKEN",
"Content-Type": "application/json",
"x-doctor": doctor_id,
"x-patient": patient_id
}
payload = {"medical_note": medical_note}
response = requests.post(url, json=payload, headers=headers)
result = response.json()
# Registrar con contexto completo
logger.info(f"Nota codificada para paciente {patient_id} por doctor {doctor_id}, run_id: {result['run_id']}")
return result
Próximos pasos
Inicio rápido
Su primera llamada
Estructura de petición
Referencia completa de campos
Ejemplos
Casos de uso reales
Referencia OpenAPI
Especificación completa