Skip to main content
POST
/
v1
/
sessions
/
{session_id}
/
redo
Undo a revert: restore the pre-revert state and the rolled-back turns.
curl --request POST \
  --url https://api.example.com/v1/sessions/{session_id}/redo \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "turn_index": 1,
  "redo_checkpoint_id": "<string>",
  "window_id": "<string>"
}
'
import requests

url = "https://api.example.com/v1/sessions/{session_id}/redo"

payload = {
"turn_index": 1,
"redo_checkpoint_id": "<string>",
"window_id": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({turn_index: 1, redo_checkpoint_id: '<string>', window_id: '<string>'})
};

fetch('https://api.example.com/v1/sessions/{session_id}/redo', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
<?php

$curl = curl_init();

curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v1/sessions/{session_id}/redo",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'turn_index' => 1,
'redo_checkpoint_id' => '<string>',
'window_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
package main

import (
"fmt"
"strings"
"net/http"
"io"
)

func main() {

url := "https://api.example.com/v1/sessions/{session_id}/redo"

payload := strings.NewReader("{\n \"turn_index\": 1,\n \"redo_checkpoint_id\": \"<string>\",\n \"window_id\": \"<string>\"\n}")

req, _ := http.NewRequest("POST", url, payload)

req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")

res, _ := http.DefaultClient.Do(req)

defer res.Body.Close()
body, _ := io.ReadAll(res.Body)

fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.post("https://api.example.com/v1/sessions/{session_id}/redo")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"turn_index\": 1,\n \"redo_checkpoint_id\": \"<string>\",\n \"window_id\": \"<string>\"\n}")
.asString();
require 'uri'
require 'net/http'

url = URI("https://api.example.com/v1/sessions/{session_id}/redo")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"turn_index\": 1,\n \"redo_checkpoint_id\": \"<string>\",\n \"window_id\": \"<string>\"\n}"

response = http.request(request)
puts response.read_body
{
  "session_id": "<string>",
  "reverted_to_turn": 123,
  "compose_text": "<string>",
  "archived_turn_count": 123,
  "document_state": {
    "html_content": "<string>",
    "document_id": "<string>",
    "version_id": "<string>",
    "chunk_count": 0,
    "last_modified": "<string>",
    "attachments": [
      {}
    ],
    "page_setup": {}
  },
  "editor_action": "update",
  "revert_changes": {},
  "dry_run": false,
  "redo_checkpoint_id": "<string>"
}
{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Headers

authorization
string | null

Path Parameters

session_id
string
required

Body

application/json

Undo a revert — restore the captured pre-revert state and the rolled-back conversation + document. Meant for use immediately after a revert (before sending a new message, which would diverge the timeline); the web app gates it to that window.

turn_index
integer
required

The turn the revert rewound to (rows at/after this were archived); redo un-archives exactly those.

Required range: x >= 0
redo_checkpoint_id
string
required

The identifier of the pre-revert state, returned by the revert response.

window_id
string | null

Optional identifier for the client window issuing the request, used to coordinate concurrent reverts from multiple browser tabs.

Response

Successful Response

Result of a session revert: restored document state and compose-box prefill.

session_id
string
required

Session identifier.

reverted_to_turn
integer
required

Turn index that the active conversation now ends at (the AI reply preceding the reverted user message). -1 when the session is reset to its initial empty state (revert from the very first user message).

compose_text
string
required

The text of the user message that was reverted. Clients should pre-fill the compose box with this so the user can edit and resend.

archived_turn_count
integer
required

Number of chat rows soft-archived by this revert (turns hidden from the UI but retained for audit).

document_state
DocumentState · object | null

Restored document state. Null when the session is reset to empty.

editor_action
string
default:update

Client instruction: 'update' to load the restored document, or 'clear' to reset the editor to empty.

revert_changes
Revert Changes · object | null

Per-document (slug -> change-set) revert diff. Applying these merges the revert onto any concurrent live edits — a conflicting section is surfaced for you to resolve rather than replacing the whole document. On dry_run this is the preview; on a real revert it is what was committed.

dry_run
boolean
default:false

Echoes the request's dry_run: when true nothing was committed/archived — this is a preview only.

redo_checkpoint_id
string | null

The identifier of the pre-revert state. Revert is non-destructive — passing this back to POST /sessions/{id}/redo (with the same turn_index) restores it and un-archives the rolled-back turns, undoing the revert. Null on a dry-run or a first-message reset.