ICSR Followup Communications
curl --request POST \
--url https://api.example.com/api/v1/icsr/{icsr_id}/followup/send \
--header 'Content-Type: application/json' \
--data '
{
"channel": "<string>",
"body": "<string>"
}
'{
"items": [
{
"id": 123,
"icsr_id": 123,
"channel": "<string>",
"direction": "<string>",
"body": "<string>",
"external_id": "<string>",
"created_at": "<string>"
}
],
"total": 123,
"id": 123,
"icsr_id": 123,
"channel": "<string>",
"direction": "<string>",
"body": "<string>",
"external_id": "<string>",
"created_at": "<string>"
}ICSR
ICSR Followup Communications
Manage followup communications with reporters via email, SMS, and WhatsApp
POST
/
api
/
v1
/
icsr
/
{icsr_id}
/
followup
/
send
ICSR Followup Communications
curl --request POST \
--url https://api.example.com/api/v1/icsr/{icsr_id}/followup/send \
--header 'Content-Type: application/json' \
--data '
{
"channel": "<string>",
"body": "<string>"
}
'{
"items": [
{
"id": 123,
"icsr_id": 123,
"channel": "<string>",
"direction": "<string>",
"body": "<string>",
"external_id": "<string>",
"created_at": "<string>"
}
],
"total": 123,
"id": 123,
"icsr_id": 123,
"channel": "<string>",
"direction": "<string>",
"body": "<string>",
"external_id": "<string>",
"created_at": "<string>"
}Endpoints
Get Followup Thread
GET /api/v1/icsr/{icsr_id}/followup/thread
admin, qf, responsable_fv, qa, direccion_tecnica, legal, or soporte
Send Followup Message
POST /api/v1/icsr/{icsr_id}/followup/send
admin, qf, responsable_fv, qa, direccion_tecnica, legal, or soporte
Path Parameters
The unique identifier of the ICSR case
Request Body (Send Message)
Communication channel to use:
email- Send via emailsms- Send via SMS (requires phone number)whatsapp- Send via WhatsApp (requires WhatsApp-enabled phone)
Message content (minimum 1 character after trimming)
Response (Get Thread)
Array of message objects in chronological order
Show Message Object Schema
Show Message Object Schema
Unique message identifier
Parent ICSR case ID
Communication channel: “email”, “sms”, or “whatsapp”
Message direction:
in- Inbound message from reporterout- Outbound message to reporter
Message content/text
External message identifier (e.g., email Message-ID, SMS ID)
Message timestamp
Total number of messages in the thread
Response (Send Message)
Returns a single message object with the same schema as thread items.Unique message identifier
Parent ICSR case ID
Channel used: “email”, “sms”, or “whatsapp”
Always “out” for sent messages
Message content that was sent
External message ID (e.g., SMTP Message-ID for email)
Message send timestamp
Contact Information Extraction
The system automatically extracts contact details from thereportante_contacto field:
- Email: Detected if the contact string contains ”@”
- Phone: Detected if the contact string is numeric or contains phone patterns
- WhatsApp: Uses the same phone number detection as SMS
reportante_email- Explicit email fieldreportante_telefono- Explicit phone field
Email Threading
When sending emails, the system implements proper email threading:- In-Reply-To Header: References the Message-ID of the last inbound message
- References Header: Includes the full chain of Message-IDs from the thread
- Message-ID Storage: Captures and stores the Message-ID of sent emails for future threading
Behavior
Auto-Status Update
When a followup message is sent:- If case status is “Pendiente” or empty, it’s updated to “En progreso”
- This indicates active communication with the reporter
- Status update is attempted but won’t block message sending if it fails
Missing Data Detection
The system can automatically send followup requests:- Trigger: New case creation or update
- Detection: System checks for missing required fields
- Rate Limiting: Only one auto-reply per hour per case
- Channel: Uses reporter’s email if available
- Template: Pre-formatted message requesting specific missing information
Message Persistence
All messages are stored in the database:- Outbound messages are logged immediately after sending
- Inbound messages are logged when received (via email polling or webhook)
- Messages are never deleted (audit trail)
- External IDs link to original emails/SMS for reference
Example Requests
Get Message Thread
GET /api/v1/icsr/1234/followup/thread
{
"items": [
{
"id": 1001,
"icsr_id": 1234,
"channel": "email",
"direction": "in",
"body": "Estimados, adjunto reporte de evento adverso con amoxicilina. Paciente presentó rash eritematoso...",
"external_id": "<abc123@hospital.com>",
"created_at": "2024-01-20T10:30:00Z"
},
{
"id": 1002,
"icsr_id": 1234,
"channel": "email",
"direction": "out",
"body": "Estimado Dr. Garcia,\n\nGracias por su reporte. Para completar la evaluación, necesitamos la siguiente información adicional:\n\n- Número de lote del producto\n- Fecha exacta de inicio del rash\n- Antecedentes de alergias del paciente\n\nSaludos,\nUnidad de Farmacovigilancia",
"external_id": "<def456@vigia.system>",
"created_at": "2024-01-20T11:15:00Z"
},
{
"id": 1003,
"icsr_id": 1234,
"channel": "email",
"direction": "in",
"body": "Buenas tardes,\n\nAdjunto la información solicitada:\n- Lote: LOT2024-001\n- Inicio del rash: 15/01/2024\n- No antecedentes de alergias conocidas\n\nSaludos",
"external_id": "<ghi789@hospital.com>",
"created_at": "2024-01-21T09:45:00Z"
}
],
"total": 3
}
Send Email Followup
POST /api/v1/icsr/1234/followup/send
{
"channel": "email",
"body": "Estimado Dr. Garcia,\n\nGracias por la información adicional. Hemos actualizado el caso y procederemos con la evaluación de causalidad.\n\nLe informaremos cuando esté lista la resolución del caso.\n\nSaludos,\nUnidad de Farmacovigilancia"
}
{
"id": 1004,
"icsr_id": 1234,
"channel": "email",
"direction": "out",
"body": "Estimado Dr. Garcia,\n\nGracias por la información adicional. Hemos actualizado el caso y procederemos con la evaluación de causalidad.\n\nLe informaremos cuando esté lista la resolución del caso.\n\nSaludos,\nUnidad de Farmacovigilancia",
"external_id": "<jkl012@vigia.system>",
"created_at": "2024-01-21T10:30:00Z"
}
Send SMS Followup
POST /api/v1/icsr/1234/followup/send
{
"channel": "sms",
"body": "VIGIA: Hemos recibido su reporte del caso #1234. Le contactaremos por email para solicitar información adicional."
}
Send WhatsApp Message
POST /api/v1/icsr/1234/followup/send
{
"channel": "whatsapp",
"body": "Hola Dr. Garcia, le escribimos de VIGIA. ¿Podría confirmar el número de lote del producto reportado en el caso #1234?"
}
Email Configuration
Email sending requires proper SMTP configuration. The system uses environment variables:SMTP_HOST- SMTP server hostnameSMTP_PORT- SMTP server port (usually 587 for TLS)SMTP_USER- SMTP usernameSMTP_PASSWORD- SMTP passwordSMTP_FROM- From email addressSMTP_FROM_NAME- From name (e.g., “VIGIA Farmacovigilancia”)
SMS Configuration
Note: SMS functionality is currently simulated. Integration with SMS gateway requires:- SMS provider API credentials
- Implementation of provider-specific API calls
- Webhook setup for delivery status tracking
WhatsApp Configuration
Note: WhatsApp functionality is currently simulated. Integration requires:- WhatsApp Business API access
- Provider credentials (e.g., Twilio, Meta)
- Message template approval
- Webhook setup for inbound messages
Error Responses
400 Bad Request - Empty Message
{
"detail": "Mensaje vacío"
}
400 Bad Request - No Contact Info
{
"detail": "Este ICSR no tiene email del reportante"
}
{
"detail": "Este ICSR no tiene teléfono"
}
{
"detail": "Este ICSR no tiene WhatsApp/teléfono"
}
400 Bad Request - Unsupported Channel
{
"detail": "Canal no soportado"
}
404 Not Found
{
"detail": "ICSR no encontrado"
}
502 Bad Gateway - SMTP Error
{
"detail": "Fallo SMTP: Connection refused"
}
Use Cases
Requesting Missing Information
- Create case with incomplete data
- System auto-sends followup email requesting missing fields
- Reporter receives email with specific data points needed
- Reporter replies with information
- Staff updates case with received data
Manual Follow-Up
- Review case and identify need for clarification
- Use GET
/followup/threadto review previous communications - Compose followup question
- POST to
/followup/sendwithchannel: "email" - System sends email with proper threading
- Message is logged in database
Multi-Channel Communication
- Initial report arrives via email
- Send email followup - no response
- Send SMS reminder after 3 days
- Send WhatsApp message with urgent cases
- All messages logged in unified thread
Reporter-Initiated Contact
- Reporter sends email to pharmacovigilance unit
- Email is received and parsed (via IMAP polling or webhook)
- System creates “in” direction message
- Message appears in thread
- Staff reviews and responds via
/followup/send
Best Practices
Email Threading
- Always use the API: Don’t send emails outside the system, as threading will break
- Check thread first: Review previous messages before sending
- Clear subject lines: System generates subject with case number
- Professional tone: Messages represent your organization
Channel Selection
- Email: Best for detailed information requests, documentation
- SMS: Good for brief reminders, urgent notifications
- WhatsApp: Useful in regions where WhatsApp is primary communication method
Response Tracking
- Monitor thread regularly for new inbound messages
- Set reminders for cases awaiting reporter response
- Escalate cases with no response after configured timeframe
- Use case status to track communication state
Privacy & Compliance
- Store minimal personal information
- Follow data retention policies for messages
- Implement proper access controls (role-based)
- Encrypt sensitive data in transit (TLS/SSL)
Automatic Followup Configuration
Environment variables control automatic followup behavior:AUTO_FOLLOWUP_ENABLED- Enable/disable automatic followup (default: true)AUTO_FOLLOWUP_DELAY_HOURS- Minimum hours between auto-followups (default: 1)REQUIRED_FIELDS- Comma-separated list of required fields to check
AUTO_FOLLOWUP_ENABLED=true
AUTO_FOLLOWUP_DELAY_HOURS=24
REQUIRED_FIELDS=paciente_peso,paciente_fecha_nacimiento,nro_lote
Related Endpoints
- Create Case - Case creation may trigger auto-followup
- Update Case - Updates may trigger auto-followup or status changes
- List Cases - Filter cases by status (“Pendiente” vs “En progreso”)
⌘I