Skip to content
Linq Copy agent prompt

Data retention

Two opt-in settings that remove WhatsApp message content from Linq's systems on a schedule, what they keep, and how to build around them.

By default, we keep message content under the standard policy described throughout this API. Two opt-in settings remove it sooner: ephemeral messages and zero-day retention. They only apply to messages created after they’re turned on, and if both are on, zero-day retention wins.

Both settings remove message content: text, attachments, and the other parts of a message. The record that a message existed stays. That means its IDs, chat, phone numbers, timestamps, direction, delivery status, and billing records.

Removed Kept
Message text Message and chat IDs
Attachment files Phone numbers
Every other part of a message’s content Timestamps and direction
Delivery status and message.sent / message.delivered / message.read events
Billing records
The attachment’s ID

They cover the copies Linq holds: our databases, storage, queues, and backups. They don’t reach Meta.

WhatsApp messages sent and received through Linq go through Meta’s hosted WhatsApp Business Platform. Meta decrypts and processes the content on its own servers and keeps its own copy under its own terms. Turning on either setting doesn’t change what Meta keeps or for how long.

Content is removed after a window set for your account, anywhere from 1 to 24 hours (24 hours by default). The window applies to your whole account, to messages you send and messages you receive, and it starts when the message is created.

A message you’re still sending keeps its content until delivery finishes, even if that runs past the window. The same goes for a message whose delivery result we’re still waiting on. Messages you receive don’t have that hold.

Once the window has passed:

  • The message disappears from transcript reads, the event log, the live stream, and replays. Transcripts normally have no gaps in their sequence numbers, and expired ephemeral messages are the one exception.
  • Its IDs, timestamps, phone numbers, direction, delivery status, and billing records stay, and keep working normally.
  • There’s no expiry timestamp in the API. If you need to know when a message will go, add your window to its created_at.
  • An idempotent retry of the send returns empty parts once the content is removed.

Removal isn’t instant. Treat the window as a minimum; content usually goes within a few minutes after it.

Messages you send Messages you receive
Where you see the content The response to your send request Your webhook deliveries for that message
Transcript, event log, stream, replays No content, ever No content, ever
How long we hold it Until delivery finishes Until every webhook endpoint has it, or has spent 35 minutes returning errors

An idempotent retry of a send returns empty parts and zero_retention: true.

For messages you receive, the webhook is the only way to get the content. The live stream and the event log never carry it, even right after the message arrives.

Content you receive is removed once every webhook endpoint subscribed to it has received it successfully, or has spent 35 minutes returning errors. Only time when your endpoint is returning errors counts. Network trouble, problems on our side, and scheduling delays don’t. One endpoint running out its 35 minutes never removes content another endpoint is still owed.

An attachment on a zero-day message has its own clock. It’s removed after your first completed download, or about 35 minutes after the webhook that carried it was received, whichever comes first. Time when our download endpoint is failing doesn’t count.

Zero-day messages carry zero_retention: true, both in webhooks and when you read them back. On every other message the field is absent. Check this field on each payload rather than keeping your own list of which numbers are zero-day, because settings can change.

message.received webhook on a zero-day number
{
"id": "evt_example",
"type": "message.received",
"timestamp": "2026-09-24T11:00:00Z",
"data": {
"message": {
"id": "msg_example",
"direction": "inbound",
"parts": [{ "type": "text", "body": "I'd like to reschedule" }],
"zero_retention": true
}
}
}
Reading the same message back later
{
"id": "msg_example",
"direction": "inbound",
"parts": [],
"zero_retention": true
}

The values are just examples. An empty parts on a zero-day message is expected, not an error.

The same attachment can belong to more than one message, for example one upload sent to several customers. We keep it until every message that uses it is due for removal and no delivery in progress still needs it. If any message using it has standard retention, the attachment stays available.

Once an attachment is removed, downloading it returns an error instead of the file.

A few things work differently from the rules above. In each case we keep content longer than the setting says; we never remove it early.

  • Backups. A backup taken before content was removed can briefly still hold it.
  • Messages received during a database outage. If we accept a message while we can’t check your settings, it’s kept under standard retention, even after things recover. We never apply a setting to it later.
  • Messages we couldn’t process. If a message runs into a processing problem after we accept it, we keep it until someone on our side resolves it by hand. This is the one case with no time limit.

Messages under either setting send, deliver, and report status like any other message. POST /v1/messages, POST /v1/chats/{chat}/messages, and the usual message.sent, message.delivered, and message.read events all work normally. Only how long we keep the content changes.

Nothing tells you when content has been removed. Save what you need from the send response or the webhook when it arrives, because that may be your only chance.

  • Save what you need when you first see it. For zero-day messages, the send response and the webhook are the only places the content appears.
  • Make sure every zero-day number has a webhook endpoint. Without one, you never receive its inbound content.
  • Download zero-day attachments right away. They’re removed after your first download, or about 35 minutes after the webhook.
  • Don’t treat an empty parts as an error on a zero-day message, or a missing message in a transcript on an ephemeral account.
  • Check zero_retention on each payload instead of guessing from the number or chat.
  • Sending messages — send routes, idempotency, and delivery outcomes
  • Attachments — upload, download, and the authenticated attachment URL
  • Webhooks — registering endpoints and verifying deliveries
  • Events and recovery — the live stream and the event log
  • Errors — the envelope and the code ranges