---
title: "Autosaves"
description: "Store draft copies of a template on your own backend at a fixed interval, so users can restore an earlier version from inside the editor."
url: https://docs.topol.io/email-editor/guide/autosaves.html
---

# Autosaves

**Autosaves write a draft copy of the current template to your backend at a fixed interval,** so an interrupted session can be restored from the editor's autosave panel.

Autosaving is off until enabled, and every draft travels through your own API endpoints, which keeps the stored history on your infrastructure.

## Enabling autosaves

Add the following setting to `TOPOL_OPTIONS`:

```ts
enableAutosaves: true,
```

## Setting the autosave frequency

The `autosaveInterval` option controls how often a draft is written. The value is in **seconds**, and the default is 60 seconds when the option is omitted.

```ts
autosaveInterval: 60 * 3, // Saves every 3 minutes
```

Values below 30 are raised to 30 seconds. **A request is only sent when the template has unsaved changes**, so an idle editor produces no autosave traffic at all.

Autosaves are attributed to a person through the current user object described in [Current user](https://docs.topol.io/email-editor/guide/current-user.html).

> **INFO**
>
> `TopolPlugin.toggleAutosaves()` opens and closes the autosave panel from your own UI.

## API integration for autosaves

Autosaves use **three separate API paths**, each configured independently. Pointing only `AUTOSAVES` at your backend is a common mistake, because the create call goes to `AUTOSAVE` instead.

| Path key | Purpose |
| --- | --- |
| `AUTOSAVES` | Lists existing autosaves |
| `AUTOSAVE` | Creates a new autosave |
| `GET_AUTOSAVE` | Retrieves one autosave by key |

> **WARNING**
>
> **Before implementing the endpoints, check [how to work with API endpoints.](https://docs.topol.io/email-editor/guide/how-to-work-with-your-api.html)**

### List Autosaves

Called to fetch the list of autosaved drafts for the current template and user.

-   URL: `/{API.AUTOSAVES}`
-   Method: `GET`
-   Params: `key`, `hostname`, `templateId`, `uuid`

**Response:**

```json
{
  "success": true,
  "data": [
    {
      "key": "autosaveKey", // used in the GET_AUTOSAVE path when retrieving this autosave
      "time": "2025-05-01T12:00:00Z", // ISO 8601 time
      "created_by": {
        "user_id": 0,
        "name": "John Doe",
        "profile_photo_url": "https://example.com/profile.jpg"
      }
    }
  ]
}
```

`key` and `time` are both required, and `time` has to be a parseable date. The list is validated as a whole, so a single malformed entry leaves the panel empty rather than dropping just that row.

`created_by` is optional and only enriches the display. When it is omitted the panel shows the timestamp alone. When it is present, all three of `user_id`, `name` and `profile_photo_url` have to be there, otherwise the editor discards the object and falls back to the timestamp.

### Create Autosave

Called when the editor creates a new autosave. Store the template JSON, the creation time, the user ID and a unique key, since that key is what the editor sends back when restoring.

-   URL: `/{API.AUTOSAVE}`
-   Method: `POST`

**Request:**

```json
{
  "definition": "{...}", // JSON string of the email template (MJML in JSON)
  "key": "api key value",
  "hostname": "origin",
  "templateId": "id of the template",
  "uuid": "userId",
  "current_user_id": "id of the current user" // provided in the current user identification object
}
```

`definition` arrives as a **serialized JSON string**, not an object. `current_user_id` is only included when a current user is configured.

**Response:**

HTTP `200 OK`

### Get a Specific Autosave

Called to retrieve a previously saved autosave by its key, which the editor appends to the `GET_AUTOSAVE` path.

-   URL: `/{API.GET_AUTOSAVE}/{autosave-key}`
-   Method: `GET`
-   Params: `key`, `hostname`, `templateId`, `uuid`

**Response:**

```json
{
  "success": true,
  "data": {
    "template": "{...}" // JSON string of the saved template
  }
}
```

`template` has to be a **JSON string**, matching what was sent as `definition`. The editor parses it, so returning a nested object here fails.
