Auto deletion fo threads or via API

Hey there!

At my company we are starting to amke use of Assistants API and it looks good, but we are worried about data retention by OpenAI.

We understand that storing threads for some time is required, but wem dont want them to be stored forever.

When are threads auto deleted(if that even happens)?
Is there any way to list the threads by API to delete them?

As for the auto deletion, I read here at the forum that it is supposed to be automatically deleted after 60 days, but the documentation says:

Objects related to the Assistants API are deleted from our servers 30 days after you delete them via the API or the dashboard. Objects that are not deleted via the API or dashboard are retained indefinitely.

so I don’t know if that changed or the documentation is not accurate.

Any idea?

Thanks

Threads are a particular entity that have a expiration assigned to them after inactivity, just so there is no expectation that OpenAI will let you rejoin a chat maintained server-side a year later. This also means you don’t have to manually manage expiration yourself or some limited storage capacity assigned to them.

“Objects” refers to things like assistants definitions or document vector stores, that you wouldn’t want expiring as a developer of the API platform. They go away when you delete them, retained just for some period of safety auditing observation by OpenAI. (you can assign an inactivity expiration to a vector store yourself, though, as they cost you money to maintain).

Hope that clarifies!

1 Like

So… are they deleted after some time? How many days?

We can potentially have protected customer data there, so we would like to be sure its deleted and not leaked in the future :smile:

That make sense, but the note I cited from the documentation is added to the threads endpoint too, that’s why I was not sure.

Thanks for your quick answer :heart:

Your original citation is correct: if unused, threads will be deleted after 60 days of inactivity. If your account was unused for 61 days, you would have 0 threads.

You can (and in most applications like matching chat to customer, must) also maintain your chat in your application database, and delete the thread ID when the user wants to delete a chat session, or reduce the time before you do your own cleanup. You’d also want to anticipate this auto-deletion so you don’t attempt to present a list of chats that cannot be continued on.

1 Like

I use the normal POST API in my C# Code.

And this is how I delete either the threds immidiatly after I am done using them or IF I see in my OpenAI Account under Dashboad>Threads that there are old threds left.

        private static async Task DeleteThread(string openAIAccessToken, string threadId)
        {
            using (var httpClient = new HttpClient())
            {
                //httpClient.Timeout = TimeSpan.FromMinutes(5); // Increase timeout
                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", openAIAccessToken);
                httpClient.DefaultRequestHeaders.Add("OpenAI-Beta", "assistants=v2");

                var response = await httpClient.DeleteAsync($"https://api.openai.com/v1/threads/{threadId}");
                var content = await response.Content.ReadAsStringAsync();

                // Print the response content
                Log($"Delete Thread Response: {content}");


                response.EnsureSuccessStatusCode();
            }
        }

Getting all still existing Threds:

        private static async Task<List<string>> ListAllThreads(string sessionKey)
        {
            using (var httpClient = new HttpClient())
            {
                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", sessionKey);

                List<string> threadIds = new List<string>();
                string lastThreadId = null;
                bool hasMore = true;

                while (hasMore)
                {
                    var url = "https://api.openai.com/v1/threads?limit=100";
                    if (lastThreadId != null)
                    {
                        url += $"&after={lastThreadId}";
                    }

                    var response = await httpClient.GetAsync(url);
                    var responseContent = await response.Content.ReadAsStringAsync();

                    // Introduce a delay to avoid hitting rate limits
                    await Task.Delay(500); // 500 ms delay between requests

                    if (response.IsSuccessStatusCode)
                    {
                        dynamic jsonResponse = JObject.Parse(responseContent);

                        foreach (var thread in jsonResponse.data)
                        {
                            threadIds.Add((string)thread.id);
                            Log($"Retrieved thread ID: {(string)thread.id}");
                        }

                        // Check if there are more items to fetch
                        hasMore = jsonResponse.data.Count > 0;
                        if (hasMore)
                        {
                            // Update the lastThreadId for the next request
                            lastThreadId = (string)jsonResponse.data.Last.id;
                        }
                        Log("Fetched a batch of threads.");
                    }
                    else
                    {
                        Log($"Failed to retrieve threads: {response.StatusCode} - {responseContent}");
                        hasMore = false;  // Exit loop on error
                    }
                }

                Log($"Total threads retrieved: {threadIds.Count}");
                return threadIds;
            }
        }

Deleting all existing Threads:

            List<string> thredIds = await ListAllThreads(openAIAccessToken);

            //EXECUTE WHEN YOU WANT TO DELETE ALL EXISTING THREADS
            // YOU HAVE TO LOGIN IN THE BROWSER AND FIND&COPY THE SESSION ID FROM THE NETWORK INSPECT, COPY AS NODE.JS FETCH; THE SESSION ID
            string sessionKey = "sess-CNjy8xgfbTvedDB6i4yzsYmOHBZZwXp6hkmk4lJL";  // Replace this with your actual current session key
            var threads = await ListAllThreads(sessionKey);
            int maxParallelism = 5; // Limit the number of concurrent tasks
            var tasks = new List<Task>();
            foreach (var threadId in threads)
            {
                tasks.Add(DeleteThread(openAIAccessToken, threadId));

                if (tasks.Count >= maxParallelism)
                {
                    await Task.WhenAny(tasks); // Wait for any task to complete
                    tasks.RemoveAll(t => t.IsCompleted); // Remove completed tasks
                }
            }
            // Wait for all remaining tasks to complete
            await Task.WhenAll(tasks);
            Log("All threads processed.");