Interactions API - Input retrieval

Hello,

I am new to this forum so I hope this is the right place for this query (and hello everyone).

I have used the Gemini API to create an internal AI studio where everyone in the company I work for has a to sign in and select a project for every generation so we can offset the cost and use it responsibly. I have a full database that saves the chat history, media generation cost history and I have linked it to the Files API, all that stuff. We are on Tier 2.

It is really successful so far, but I am currently using contentGeneration.

I have switched a local version to the Interactions API and it all works (chat, nano banana, tools, files API chat, file search chat etc.). I have done this to save token cost on sending the full chat history every query and it has better cross model integration (as I understand). I also want to add Omni.

I am currently looking to integrate it into my studio version with the database and instead of saving the full chat history, I want to save the previous_interaction_id.

I have run into a few problems if anyone can help. Firstly, I thought about linking the chain of previous_interaction_id’s and populating the chat history, similarly to how I have populated the chat history using the database. This would essentially reduce my database chat history to just one string. I can retrieve the previous interaction id output but it doesn’t seem possible to retrieve the input.

In the logs, the previous_interaction_id is in the input and I cannot retrieve this. Is this not possible for security reasons?

I could save the full history as well as the previous_interaction_id and just use the previous_interaction_id to continue the chat, but then it will all unlink after the 55 day cache removal period. I could look to send full history if the previous_interaction_id isn’t available, but the latest chat interaction might still be live, but the interaction 7 responses ago might have been deleted.

So, has anyone managed to retrieve the previous interaction input? Is it possible to get the previous_interaction_id of the previous_interaction_id?

Thank you for the long read and I am open to any ideas or responses.

Hi Elliot,

Thanks for contributing and also for using our new Interactions API for your integration.

I was looking into this an unable to reproduce error. Is it possible to give the code snippet you were trying to run?

I want to clarity some things:

  • When you GET an interaction, you should be able to see the convo for that “turn” by inspecting the “steps” field. You’ll see different step types like “user_input” for your input and “model_output” for what the model produced. Each successful turn (happy path) includes both in the GET
  • When you POST an interaction (create a new interaction), the interaction resource that is return to you only includes steps the model produced (e.g output, thoughts, tool calls, etc.)
  • each Interaction represents only one turn so you won’t see previous turns user_input/model_output steps. To see that you need to GET the chained “previous_interaction_id”

I’d be hesitant to reduce the database history to only the previous_interaction_id, even if chaining works reliably.

For a workflow where conversations may need to be resumed weeks later, I’d treat the interaction ID as a continuation mechanism rather than the permanent source of truth. Keeping a lightweight local record of the user input, final model output, interaction ID, timestamp, and any important structured fields gives you a fallback if part of the remote chain expires or becomes unavailable.

This also seems useful for workflows where an interaction leads to a real action — for example, processing uploaded photos, categorizing items, or generating an estimate — because you can preserve the result without storing every intermediate model step.

Trey’s clarification about GET returning the user_input and model_output steps makes the chaining approach much more useful, but I’d still keep that small local audit trail rather than depending entirely on the interaction chain.

I’d be interested to know whether you’re planning to keep any local snapshot/checkpoint every few turns, or whether the goal is eventually to make the Interactions API the only conversation store.

Hi Trey,

Thank you for the reply, I am UK based so just missed this yesterday.

I use a cloud run function node server and I am passing the interaction ID of the previous interaction to the server. Here is a selection of code snippets and the logs I am getting server side.

Firstly, this is the code on my server:

const url = `https://generativelanguage.googleapis.com/v1beta/interactions/${currentId}?key=${apiKey}`;

const apiResponse = await fetch(url);

const interaction = await apiResponse.json();

console.log("RAW GEMINI RESPONSE");

console.log(JSON.stringify(interaction, null, 2));

I get this response:

=================== RAW GEMINI RESPONSE ===================
{
“id”: “v1_###################################################################”,
“status”: “completed”,
“usage”: {
“total_tokens”: 838,
“total_input_tokens”: 22,
“input_tokens_by_modality”: [
{
“modality”: “text”,
“tokens”: 22
}
],
“total_cached_tokens”: 0,
“total_output_tokens”: 305,
“total_tool_use_tokens”: 0,
“total_thought_tokens”: 511
},
“created”: “2026-08-04T15:42:42Z”,
“updated”: “2026-08-04T15:42:42Z”,
“service_tier”: “standard”,
“steps”: [
{
“signature”: “THOUGHT_SIGNATURE”,
“type”: “thought”
},
{
“content”: [
{
“text”: “RESPONSE_TEXT”,
“type”: “text”
}
],
“type”: “model_output”
}
],
“object”: “interaction”,
“model”: “gemini-3.1-pro-preview”
}

So model_output is in there but no user_input.

When trying to parse it I can get the model_output but the input is obviously empty given the above log. I know it uses snake formatting but I have tried both ways:

const steps = interaction.steps || interaction.Steps;

if (steps && Array.isArray(steps)) {
for (const step of steps) {
  const type = (step.type || "").toLowerCase();
  const content = step.content || step.Content;

  if (content && Array.isArray(content)) {
    const partsText = content.map(part => {
      if (typeof part === "string") return part;
      return part.text || "";
    }).join("");

    if (type === "model_output" || type === "modeloutput") {
      modelText += partsText;
    } else if (type === "user_input" || type === "userinput") {
      userText += partsText;
    }
  }
}
}

The example response on the API documentation page also only seems to have the output:

{
“created”: “2025-11-26T12:25:15Z”,
“id”: “v1_ChdPU0F4YWFtNkFwS2kxZThQZ05lbXdROBIXT1NBeGFhbTZBcEtpMWU4UGdOZW1…”,
“model”: “gemini-3.6-flash”,
“object”: “interaction”,
“status”: “completed”,
“steps”: [
{
“type”: “model_output”,
“content”: [
{
“type”: “text”,
“text”: “I’m doing great, thank you for asking! How can I help you today?”
}
]
}
],
“updated”: “2025-11-26T12:25:15Z”
}

In my logs on AI studio, the input and output are separated. This is an example of the input in my logs:

{
“stream”: true,
“store”: true,
“steps_enabled”: true,
“previous_interaction_id”: “v1_##########################”,
“object”: “interaction”,
“input”: [
{
“type”: “user_input”,
“content”: [
{
“text”: “is it warm there?”,
“type”: “text”
}
]
}
],
“model”: “gemini-3.1-pro-preview”,
“generation_config”: {
“thinking_level”: “high”
}
}

So yeah I seem to just be getting the output. I may be doing something silly so any help would be fantastic.

If you would like any more of my code I am happy to post more.

Yeah I am currently trying to think of the best way. I really like the work I have done with saving the history, I save what tools were used on the prompt, what files were used from files understanding and what citations were used from the file search and render it all out in a nicely formatted chat. So it would be a shame to remove all that.

I don’t save nano bananas, tts’s or veo’s though as I don’t want to save the huge base64 strings to the database. These are all single hit’s as I also didn’t want to send base64 strings in the history to generate a tweak. This new interactions API would sort this as I’d only be sending the current prompt so I am keen to use it.

With currently saving the history and the previous_interaction_id, I could get into a situation where the user could visibly see their full history in the chat from the database, but it all won’t actually be sent to Gemini as it will have been removed from the cache. This would be worse for me than have some of the history be removed when the 55 days is up. It’s a difficult one but I’ll let you know what I come up with.

Hello again,

It’s been a few days since I shared some code in the hope of retrieving the input from a successful interaction (and therefore the previous_interaction_id).

Has anyone had a chance to look into this or reproduce it in their own projects?

I’m thinking that only the output is retrievable and that this is just how the architecture currently works. However, I’m very open to being proved wrong!

Hi there sorry for the late reply! lettign you know im passing this to our engineer team to look at this, when you GET the interaction you should get user_input (the entire convo from that turn), reducing the need to store entire history in DB on your side

This may be a bug, but let me confirm after we finish looking into this

Hi Elliot,

Thanks for bringing this issue. We’ve managed to reproduce it and are now handling it internally.

Best regards,
Jackob

Oh that’s good news, I was wracking my brain trying to add extra fields to the URL. Thanks both for looking into the issue and I’m happy to have been a help.

Thanks,
Elliot

Not the answer you want, but I think the chain can’t do what you’re asking it to.

On retrieval: you’re right that outputs come back and inputs don’t. I’d stop treating that as a gap to work around — even if it were exposed, you’d still be building durable storage on a 55-day fuse.

The bug I’d fix first, because it’ll bite quietly: your fallback assumes chain liveness is monotonic. It isn’t. Expiry is per-interaction, not per-chain, so the head can be live while interaction seven is already gone. Nothing errors — you just get a conversation with a hole in the middle. Testing this won’t surface it, because it takes 55 days to appear.

A durable path for the inputs, if you specifically need them: they’re in the Logs payload — full prompt and response, prior-turn context, and a direct link to the previous_interaction_id. Logs expire on the same window (configurable down to 7/14/28), unless saved to a dataset, and datasets don’t expire. It’s an export, not an API read, but it’s the only version of that data that outlives retention.

The reframe I’d suggest. Rather than sorting context by project, sort it by lifetime:

  • Permanent — glossary, style, reference docs. Your DB. Never touched by expiry.
  • Carry-forward — the distillate of a conversation: decisions, constraints, artifacts produced. Small. Your DB.
  • Ephemeral — the turn-by-turn transcript. Let it expire.

Then the id-chain is a hot cache for live conversations and nothing more. A dead id doesn’t mean a hole, it means rehydrate from the distillate. No fallback logic, no chain-integrity problem.

It does kill the one-string goal — but your DB gets much smaller than the full transcript you’re storing now, and it stops being hostage to someone else’s retention window.

Two things worth knowing given your cost setup. Storing interactions doesn’t bill you — previous_interaction_id uses implicit caching, no storage fee. What you pay for is what gets loaded: every token of carry-forward is re-read as input on every rehydrate, forever. Archive is free, context is rent.

And the API won’t split spend by project for you at any scale, which I assume is why you built the attribution yourself — worth knowing that none of this will show up in your invoice either way. You’ll be measuring by inference.

Hello everyone,

I just tested loading the Interactions API history and the GET does now include the user_input and previous_interaction_id and my load script now brings in the whole history of the conversation using just the latest interaction id!

It works really well so thank you Trey, Jackob and the internal team for looking into this.

I have been thinking about the 55 day interaction store limit (and asking around internally) and I rarely continue a conversation from that far ago. If I use AI to help with coding, bug fixing, scripting, then the content will have been copied over and most likely edited and tweaked manually so the logs are out of date anyway. I usually start a new fresh thread for any new queries as I feel the AI is more open minded instead of hyper focusing on one path with a large conversation history.

Anyway, probably one for a different thread. I look forward to combining this Interactions API with my database (whatever way I choose) and rolling it out.

Many thanks,
Elliot