Message Archiving
Message Archiving allows you to preserve campaign messages across various channels for customer service and regulatory compliance purposes. When enabled, each message sent during a campaign is archived and stored in your external storage bucket (e.g., Amazon S3 or GCS).
How It Works
Once you've set up your storage credentials, message archiving happens automatically:
- Your campaign messages are automatically captured when sent
- Messages are archived to your configured storage location
- Files are organized according to your path configuration
The process happens seamlessly in the background without affecting campaign performance. As long as valid credentials are configured, all eligible messages will be archived.
Configuring Message Archiving
To enable message archiving:
- Navigate to Settings
- Select the Credentials in the Message Archiving section
- Configure your storage credentials and path settings
![]() | ![]() |
Path Configuration
You can customize how archived messages are organized in your storage by configuring the order of path components in the Path builder section under Credentials. This determines the folder structure in which your files will be stored in your bucket.
The Path builder shows available components like:
- brand/
- customerId/
- campaignType/
- campaignId/campaignSeriesId/
- channel/
- contact
You can drag these components to change their order in the path. For example, if you arrange them as shown in the screenshot (brand → customerId → campaignType → campaignId/campaignSeriesId → channel → contact), your archived messages would be stored in a path structure like:
/brandname/hashedcustomerid/campaigntype/campaignid_or_seriesid/channel/hashedcontact/message_filename.json
You can customize how archived messages are organized in your storage by configuring path components in the Path builder section under Credentials. For example, you might organize files by:
- Campaign ID
- Campaign Series ID
- Channel
- Brand
- Other available parameters
Identifier Hashing
Customer ID and contact values are hashed to ensure compatibility with storage folder naming restrictions:
- We hash customerId and contact values using SHA-1
- Implementation:
createHash('sha1').update(data).digest('hex')
Note for searching archived messages: To locate messages for a specific customer or contact, you'll need to generate the same SHA-1 hash of the identifier before searching in your storage system.
Example Archived Messages
Messages will follow this structure:
{
"version": 1,
"tenantId": 9999,
"customerId": "505e5267-b01e-4f89-8082-bcddcdb71d7c",
"channel": "optimail",
"sentAt": "2025-07-08T08:29:44Z",
"metadata": {
"actionId": 32,
"brand": "AC05",
"campaignId": 6102,
"campaignSeriesId": 24,
"campaignType": "triggered",
"templateId": 361,
"templateName": "Welcome Email"
},
"content": {
"EmailContent": {
"from": "[email protected]",
"fromName": "Optimove",
"to": "[email protected]",
"subject": "Welcome to Optimove",
"headers": {},
"htmlBody": "<!DOCTYPE html><html><head><meta charset=\"UTF-8\" /><title>Welcome!</title></head><body style=\"font-family: Arial, sans-serif; background-color: #F9F9F9; padding: 20px;\"><table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" style=\"max-width: 600px; margin: auto; background-color: #FFFFFF; padding: 20px; border: 1px solid #ddd;\"><tr><td><h2 style=\"color: #333;\">Welcome to [Your Company Name]!</h2><p>Hi Jim,</p><p>Thanks for signing up! We're excited to have you on board.</p><p>To get started, just click the button below:</p><p><a href=\"https://yourcompany.com/dashboard\" style=\"background-color: #007BFF; color: white; padding: 10px 15px; text-decoration: none; border-radius: 4px;\">Get Started</a></p><p>If you have any questions, just reply to this email.</p><p>Best regards,<br />The [Your Company] Team</p></td></tr><tr><td style=\"text-align: center; font-size: 12px; color: #888; padding-top: 20px;\">© 2025 Optimove. All rights reserved.</td></tr></table></body></html>"
}
}
}{
"version": 1,
"tenantId": 3013,
"customerId": "exampleCustomerId",
"channel": "optimobile_push",
"sentAt": "2025-04-16T10:27:21Z",
"metadata": {
"brand": "Your Brand Name",
"campaignId": 12345,
"campaignSeriesId": 1999,
"campaignType": "triggered",
"templateId": 1744799126438,
"templateName": "Test push template",
"actionId": 789
},
"content": {
"platform": "ios",
"to": "examplePushToken...",
"payload": {
"headers": {
"apns_push_type": "alert",
"apns_expiration": 1745058441,
"apns_priority": 10,
"apns_topic": "com.optimove.sdk.optimovemobileclientnofirebase",
"apns_collapse_id": null
},
"body": {
"aps": {
"sound": "default",
"content_available": null,
"alert": {
"title": "Push notification title",
"body": "Push notification body"
},
"mutable_content": 1,
"category": null,
"interruption_level": null,
"relevance_score": null,
"badge": null
},
"attachments": {
"pictureUrl": "https://someimageurl.com/image.png"
},
"custom": "{\"a\":{\"k.message\":{\"type\":1,\"data\":{\"id\":4195}}}}"
}
}
}
}{
"version": 1,
"tenantId": 9999,
"customerId": "4737493",
"channel": "optimobile_web_push",
"sentAt": "2025-07-08T02:21:53Z",
"metadata": {
"actionId": 789,
"brand": "Your Brand",
"campaignId": 498413022,
"campaignSeriesId": 1999,
"campaignType": "triggered",
"templateId": 1749559757627,
"templateName": "Welcome Template"
},
"content": {
"PushContent": {
"platform": "web",
"to": "https://fcm.googleapis.com/fcm/send/dzRU3x1t94c:APA91bE5lkoRSrMer9mEEBJpK",
"payload": {
"W3cRequest": {
"title": "Welcome!",
"msg": "Welcome to Optimove",
"data": "{\"k.message\":{\"type\":1,\"data\":{\"id\":23267}}}",
"url": "https://www.optimove.com",
"image": "optimove.png",
"icon": null
}
}
}
}
}{
"version": 1,
"tenantId": 3013,
"customerId": "exampleCustomerId",
"channel": "optitext_sms",
"sentAt": "2025-03-20T12:22:06Z",
"metadata": {
"brand": "Your Brand Name",
"campaignId": 32,
"campaignSeriesId": 32,
"campaignType": "scheduled",
"templateId": 1741687511620,
"templateName": "Test Sms Template"
},
"content": {
"from": "000000000000",
"to": "000000000000",
"payload": {
"body": "Hello. This is an example sms message."
}
}
}{
"version": 1,
"tenantId": 3013,
"customerId": "unknown",
"channel": "optitext_sms",
"sentAt": "2026-04-29T12:43:02Z",
"metadata": {
"brand": "Your Brand Name",
"campaignId": 0,
"campaignSeriesId": 0,
"campaignType": "on_demand",
"templateId": 0,
"templateName": "on-demand",
"actionId": 0
},
"content": {
"from": "0000",
"to": "000000000000",
"payload": {
"body": "You have successfully unsubscribed from SMS messages. You can resubscribe at any time from your account preferences."
}
}
}Note: In the archived messages, the "channel" field uses these specific string mappings:
| Channel Name | Mapping |
|---|---|
| 'optimail' | |
| Mobile Push | 'optimobile_push' |
| Mobile WebPush | 'optimobile_web_push' |
| SMS | 'optitext_sms' |
System-Generated Messages
Not every archived message belongs to a campaign. Optimove also sends on-demand messages — messages generated in reaction to something a customer did, rather than as part of a scheduled or triggered campaign. For example, when a customer replies STOP to an SMS, Optimove automatically sends a confirmation that they have been unsubscribed. These SMS auto-replies are archived with campaignType: "on_demand".
These messages are archived exactly like campaign messages, and they have always been included in Message Archiving. They are not malformed files. The difference is in the identifiers. A customer can reply at any time, so the auto-reply is not tied to a campaign. And Optimove sends the auto-reply to the phone number that messaged in without looking that number up in the customer database, so there is no customer ID either. The archived record therefore carries placeholder values rather than real ones:
| Field | Value in an on-demand message | Why |
|---|---|---|
customerId | "unknown" | The reply goes to the phone number that messaged in. Optimove does not look that number up in the customer database. |
campaignId | 0 | A customer can reply at any time, so the auto-reply is not tied to a campaign. |
campaignSeriesId | 0 | No originating campaign series. |
templateId | 0 | No template — the body is system-generated. |
templateName | "on-demand" | Fixed literal identifying the message as on-demand. |
actionId | 0 | No campaign action. |
campaignType | "on_demand" | Identifies SMS auto-replies and separates them from scheduled and triggered campaign messages. |
Note: These records carry placeholder IDs, so make sure your ingestion pipeline accepts them. Use
campaignType: "on_demand"to identify them.
On-demand messages cannot be linked to a campaign or a customer ID. The only identifier is the recipient's phone number in
content.to. To trace an auto-reply back to the inbound message that triggered it, matchcontent.toagainst the sender numbers in your own records.
Error Handling
The Message Archiving Errors page displays issues that you can resolve, such as:
- Storage authentication failures
- Permission errors
- Configuration issues
Each error includes details to help you troubleshoot and resolve the issue.
Best Practices
- Regularly verify your storage credentials
- Implement appropriate retention policies for archived messages
- Test the archiving configuration before running large campaigns
Updated 4 days ago


