Import messages and contacts with date range
Currently, the Evolution API does not provide a way to retrieve messages and contacts based on a date range. This limits the ability to perform historical analysis and data synchronization for systems that need to maintain an interaction history.
It would be useful to have an endpoint that allows requesting messages and contacts filtered by date. A possible implementation for this feature could be:
Suggested Implementation:
- A new endpoint, such as
/messages/historyand/contacts/history, that accepts date parameters (start_dateandend_date).
Benefits:
- Enables retrieving old messages without relying solely on real-time events.
- Facilitates data migration and synchronization in external systems.
- Reduces the need to store all messages locally for future queries.
If this functionality already exists in some way, please clarify how we can use it. Otherwise, this improvement would greatly enhance the scalability of the API.
Thank you! π
I have a issue that will benefit from this solution. my chatwoot crashed but evolution API has been collecting the messages diligently behind the scene. When chatwoot came online, the messages were not imported and i have about 3 days of missing data.
I would be helpful for me too! ;)
+1 here
`# Adding fetchMessageHistory to Evolution API - Correct Implementation Guide
Based on the actual Evolution API repository structure, here's how to add the fetchMessageHistory functionality.
Actual Evolution API Structure
From the main.ts file and error traces, the real structure is:
src/
βββ api/
β βββ integrations/
β β βββ channel/
β β β βββ whatsapp/
β β β βββ whatsapp.baileys.service.ts
β β βββ chatbot/
β β βββ event/
β β β βββ webhook/
β β βββ rabbitmq/
β βββ routes/
β β βββ index.router.ts
β βββ server.module.ts
β βββ provider/
βββ config/
βββ docs/
βββ main.ts
Step 1: Add the Method to the Baileys Service
File: src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts
This is where you need to add the fetchMessageHistory method. Based on the error traces, this file already contains message handling logic.
// Add this method to the existing WhatsAppBaileysService class
public async fetchMessageHistory(data: {
count: number;
oldestMsgId: string;
oldestMsgRemoteJid: string;
oldestMsgFromMe?: boolean;
oldestMsgTimestamp: number;
}): Promise<string> {
try {
// Validate that the client is connected
if (!this.client || this.instance.connectionStatus !== 'open') {
throw new Error('WhatsApp client is not connected');
}
// Create the message key object as Baileys expects it
const oldestMsgKey = {
id: data.oldestMsgId,
remoteJid: data.oldestMsgRemoteJid,
fromMe: data.oldestMsgFromMe || false
};
// Call the Baileys fetchMessageHistory function
const messageId = await this.client.fetchMessageHistory(
data.count,
oldestMsgKey,
data.oldestMsgTimestamp
);
this.logger.log(`Message history fetch requested with ID: ${messageId}`);
return messageId;
} catch (error) {
this.logger.error('Error fetching message history:', error);
throw new Error(`Failed to fetch message history: ${error.message}`);
}
}
Step 2: Create DTO for Request Validation
File: src/api/dto/fetchMessageHistory.dto.ts (create this file)
import { IsBoolean, IsNotEmpty, IsNumber, IsOptional, IsString } from 'class-validator';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
export class FetchMessageHistoryDto {
@ApiProperty({
description: 'Number of messages to fetch',
example: 50,
minimum: 1,
maximum: 100
})
@IsNotEmpty()
@IsNumber()
count: number;
@ApiProperty({
description: 'ID of the oldest message as reference',
example: 'BAE5F8D123456789'
})
@IsNotEmpty()
@IsString()
oldestMsgId: string;
@ApiProperty({
description: 'Remote JID of the oldest message',
example: '[email protected]'
})
@IsNotEmpty()
@IsString()
oldestMsgRemoteJid: string;
@ApiPropertyOptional({
description: 'Whether the oldest message is from the user (true) or contact (false)',
example: false,
default: false
})
@IsOptional()
@IsBoolean()
oldestMsgFromMe?: boolean;
@ApiProperty({
description: 'Timestamp of the oldest message (Unix timestamp)',
example: 1640995200
})
@IsNotEmpty()
@IsNumber()
oldestMsgTimestamp: number;
}
Step 3: Add Route to the Router
File: src/api/routes/index.router.ts
Look at how other routes are defined in this file and add the new route. Based on the sendText endpoint pattern:
// Add this to the existing router configuration
// This should be added where other message routes are defined
router.post('/message/fetchHistory/:instanceName',
// Add your middleware here (auth, validation, etc.)
async (req, res) => {
try {
const { instanceName } = req.params;
const data = req.body as FetchMessageHistoryDto;
// Get the instance (this will depend on how instances are managed)
const waMonitor = /* get your wa monitor instance */;
const instance = waMonitor.waInstances[instanceName];
if (!instance) {
return res.status(404).json({
error: 'Instance not found',
message: `Instance ${instanceName} does not exist`
});
}
// Call the service method
const messageId = await instance.fetchMessageHistory(data);
return res.status(200).json({
success: true,
messageId,
message: 'Message history fetch initiated successfully',
data: {
count: data.count,
oldestMsgId: data.oldestMsgId,
oldestMsgRemoteJid: data.oldestMsgRemoteJid,
oldestMsgTimestamp: data.oldestMsgTimestamp
}
});
} catch (error) {
console.error('Error in fetchMessageHistory route:', error);
return res.status(500).json({
error: 'Internal server error',
message: error.message
});
}
}
);
Step 4: Alternative Implementation Using Express Router Pattern
If the routing follows a more traditional Express pattern, create a dedicated router file:
File: src/api/routes/message.router.ts (if this doesn't exist, create it)
import { Router } from 'express';
import { validate } from 'class-validator';
import { FetchMessageHistoryDto } from '../dto/fetchMessageHistory.dto';
const messageRouter = Router();
messageRouter.post('/fetchHistory/:instanceName', async (req, res) => {
try {
const { instanceName } = req.params;
// Validate DTO
const dto = Object.assign(new FetchMessageHistoryDto(), req.body);
const errors = await validate(dto);
if (errors.length > 0) {
return res.status(400).json({
error: 'Validation failed',
details: errors
});
}
// Your implementation here following the pattern used in Evolution API
} catch (error) {
return res.status(500).json({
error: 'Internal server error',
message: error.message
});
}
});
export { messageRouter };
Step 5: Add to Swagger Documentation
File: src/docs/swagger.conf.ts
Add the endpoint documentation following the existing pattern in this file:
// Add to the existing swagger configuration
{
"/message/fetchHistory/{instanceName}": {
"post": {
"tags": ["Message"],
"summary": "Fetch message history from WhatsApp",
"parameters": [
{
"name": "instanceName",
"in": "path",
"required": true,
"schema": {
"type": "string"
},
"description": "Name of the WhatsApp instance"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FetchMessageHistoryDto"
}
}
}
},
"responses": {
"200": {
"description": "Message history fetch initiated successfully"
},
"400": {
"description": "Bad request"
},
"404": {
"description": "Instance not found"
},
"500": {
"description": "Internal server error"
}
}
}
}
}
Step 6: Update Types and Interfaces
File: src/types/message.types.ts (create if it doesn't exist)
export interface IMessageHistoryRequest {
count: number;
oldestMsgId: string;
oldestMsgRemoteJid: string;
oldestMsgFromMe?: boolean;
oldestMsgTimestamp: number;
}
export interface IMessageHistoryResponse {
success: boolean;
messageId: string;
message: string;
data: IMessageHistoryRequest;
}
Important Implementation Notes
-
Instance Management: Study how other endpoints get the WhatsApp instance. Look at existing endpoints like
sendTextto understand the pattern. -
Authentication: Follow the same authentication pattern used by other endpoints (likely API key validation).
-
Error Handling: Use the same error handling pattern as other endpoints in the codebase.
-
Validation: Use the same validation middleware used by other endpoints.
-
Logging: Follow the logging pattern used throughout the codebase.
Usage Example
Once implemented, you can use it like this:
curl --request POST \
--url https://your-server.com/message/fetchHistory/your-instance \
--header 'Content-Type: application/json' \
--header 'apikey: your-api-key' \
--data '{
"count": 50,
"oldestMsgId": "BAE5F8D123456789",
"oldestMsgRemoteJid": "[email protected]",
"oldestMsgFromMe": false,
"oldestMsgTimestamp": 1640995200
}'
Python Client Example
import requests
def fetch_message_history(base_url, api_key, instance_name, count, oldest_msg_id,
oldest_msg_remote_jid, oldest_msg_timestamp, oldest_msg_from_me=False):
url = f"{base_url}/message/fetchHistory/{instance_name}"
headers = {
'Content-Type': 'application/json',
'apikey': api_key
}
payload = {
"count": count,
"oldestMsgId": oldest_msg_id,
"oldestMsgRemoteJid": oldest_msg_remote_jid,
"oldestMsgFromMe": oldest_msg_from_me,
"oldestMsgTimestamp": oldest_msg_timestamp
}
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 200:
return response.json()
else:
raise Exception(f"API call failed: {response.status_code} - {response.text}")
# Usage
try:
result = fetch_message_history(
base_url="https://your-evolution-api.com",
api_key="your-api-key",
instance_name="your-instance",
count=50,
oldest_msg_id="BAE5F8D123456789",
oldest_msg_remote_jid="[email protected]",
oldest_msg_timestamp=1640995200
)
print(f"Message history fetch initiated: {result['messageId']}")
except Exception as e:
print(f"Error: {e}")
Next Steps
-
Study the Codebase: Look at how
sendTextand other message endpoints are implemented - Follow the Pattern: Use the same architecture and patterns as existing endpoints
- Test Thoroughly: Test with different message types and scenarios
- Add Tests: Create unit tests following the existing test structure
- Submit PR: Once working, submit a pull request to help the community
This implementation exposes the Baileys fetchMessageHistory function through Evolution API's REST interface, maintaining consistency with the existing codebase architecture.
`
@the-rock posting a claude solution doesn't help so much. The best would be run the code locally, test it and submit as a pull request.
Segundo a doc do Baileys se passarmos uma info de Desktop na opΓ§Γ£o browser, pode pegar mais mensagens
O Evolution estΓ‘ usando o padrΓ£o
https://github.com/EvolutionAPI/evolution-api/blob/9cdb897a0fb1b3c2391699d2df053abd360229cf/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts#L534
SerΓ‘ que podemos ter um resultado diferente?
Is this already implemented? It's been marked as completed but I can't find how to do it.