Chat with us, powered by LiveChat
← Return to MyDisct Solver

Close Session

The POST /session/close endpoint terminates an active BBRE (Browser-Backed Request Engine) session and immediately releases all server-side resources associated with it. When you close a session, the BBRE engine destroys the browser context that was allocated during session creation, which means all cookies, fingerprint state, JavaScript execution context, DOM state, and navigation history tied to that session are permanently discarded. The session status transitions to closed, and no further requests can be made through it. Closing a session also frees up one of your 10 active session slots, allowing you to create new sessions without hitting the SESSION_LIMIT_REACHED limit. This is a critical resource management operation that every BBRE integration should implement properly. Without explicit session closure, your sessions remain active until they expire naturally based on the timeout value set during creation. During that idle time, they continue to consume server resources and count toward your active session limit, which can block new session creation when you need it most. The close operation is idempotent in the sense that calling it on an already-closed session returns a clear error rather than causing unexpected behavior, so you can safely implement retry logic around session cleanup without worrying about side effects. This page provides complete documentation for the session close endpoint, including the request format, authentication requirements, response structure, error handling, SDK integration, and best practices for session lifecycle management.

Why Closing Sessions Matters

Every active BBRE session holds a dedicated browser context on the server, including memory for cookies, fingerprint data, and in adaptive mode, a full browser instance with its own process. Your account is limited to 10 active sessions at any time. If you do not close sessions when your workflow finishes, they remain active until the timeout expires, which means you are wasting session slots that could be used for new workflows. Always close sessions explicitly using this endpoint when you are done. Implement a try/finally or try/catch/finally pattern in your code to ensure sessions are closed even when errors occur during your workflow. This is the single most important best practice for BBRE session management.

Endpoint

POST https://bbre-solver-api.mydisct.com/session/close

Authentication

All requests to the BBRE API require authentication via an API key. You must include your API key in the HTTP headers of every request, including session close operations. The API accepts the key through either the x-api-key header or the apikey header. Both header names are supported and functionally identical. The API key used to close a session must belong to the same account that created the session. You cannot close sessions that belong to other accounts. If no API key is provided, the API returns a 401 error with the API_KEY_REQUIRED error code. If the provided key is invalid or belongs to a suspended or inactive account, the API returns a 403 error with the appropriate error code (INVALID_API_KEY, ACCOUNT_SUSPENDED, or ACCOUNT_INACTIVE).

Header Type Required Description
x-api-key string required Your BBRE API key. You can find this in your MyDisct Solver dashboard.
Content-Type string required Must be set to application/json for all requests.

Request Body Parameters

The request body must be a JSON object containing the session ID of the session you want to close. The sessionId parameter is the only parameter accepted by this endpoint and it is required. The session ID is the unique identifier that was returned when you created the session using the POST /session/create endpoint. If you do not provide a session ID, the request validator returns a 400 SESSION_ID_REQUIRED error before the request reaches the controller. The session ID format is a string that typically starts with session_ followed by an alphanumeric identifier, but you should treat it as an opaque string and always use the exact value returned by the session creation endpoint.

Parameter Type Required Description
sessionId string required The unique session identifier returned by the POST /session/create endpoint. This is the session.id field from the creation response. The session must belong to the authenticated user. If the session does not exist or belongs to a different account, the API returns a 404 SESSION_NOT_FOUND error. If the session has already been closed, the API returns a 400 SESSION_CLOSED error.

When to Close Sessions

Knowing when to close a session is just as important as knowing how to close one. The general rule is simple: close a session as soon as you no longer need it. However, there are several specific scenarios where session closure is the correct action, and understanding these scenarios helps you build more robust and resource-efficient integrations.

1. Workflow Completion

The most common scenario for closing a session is when your multi-step workflow has finished successfully. For example, after you have logged into a website, navigated to the target page, extracted the data you need, and stored it in your database, the session has served its purpose and should be closed immediately. There is no benefit to keeping the session alive after the workflow is complete, and doing so wastes one of your 10 active session slots. Always place the close call at the end of your workflow logic, ideally inside a finally block to ensure it executes regardless of whether the workflow succeeded or failed.

2. Error Recovery

When your workflow encounters an unrecoverable error, such as the target website returning an unexpected response, a critical page being unavailable, or your application logic detecting that the workflow cannot proceed, you should close the session before handling the error. This prevents orphaned sessions from accumulating and consuming your session slots. Even if you plan to retry the workflow, it is better to close the current session and create a fresh one for the retry attempt, because the existing session may have accumulated state (cookies, navigation history) that contributed to the failure.

3. Session Slot Management

If your application needs to create a new session but you are approaching or have reached the 10-session limit, you should close the oldest or least-needed active session to free up a slot. Use the POST /account/sessions endpoint to list your active sessions and identify candidates for closure. Sessions that have been idle for a long time or that belong to completed workflows are the best candidates. Implementing a session pool pattern where you proactively manage session lifecycle prevents the SESSION_LIMIT_REACHED error from disrupting your application flow.

4. Application Shutdown

When your application is shutting down (whether gracefully or due to a crash), you should close all active sessions as part of the shutdown procedure. Register a shutdown handler (such as listening for SIGTERM or SIGINT signals in Node.js, or using atexit in Python) that iterates through your tracked session IDs and closes each one. This ensures that server resources are released promptly and your session slots are freed for the next time your application starts. If your application crashes without closing sessions, those sessions will remain active until their timeout expires.

Request Examples

The following examples demonstrate how to close a BBRE session in different programming languages and for different use cases. All examples show complete, working code that you can copy and run directly. Remember to replace YOUR_API_KEY with your actual BBRE API key and session_abc123def456 with the session ID returned by the session creation endpoint.

Basic Session Close

The simplest way to close a session. This sends the session ID to the close endpoint and logs the result. Use this pattern when you have a single session to close at the end of your workflow.

JavaScript
const axios = require("axios");

const API_BASE = "https://bbre-solver-api.mydisct.com";
const API_KEY = "YOUR_API_KEY";

async function closeSession(sessionId) {
  const response = await axios.post(
    API_BASE + "/session/close",
    { sessionId: sessionId },
    {
      headers: {
        "Content-Type": "application/json",
        "x-api-key": API_KEY
      }
    }
  );

  console.log("Session closed:", response.data.data.session.id);
  console.log("Status:", response.data.data.session.status);

  return response.data;
}

closeSession("session_abc123def456");
Python
import requests

API_BASE = "https://bbre-solver-api.mydisct.com"
API_KEY = "YOUR_API_KEY"

headers = {
    "Content-Type": "application/json",
    "x-api-key": API_KEY
}

response = requests.post(
    API_BASE + "/session/close",
    headers=headers,
    json={"sessionId": "session_abc123def456"}
)

data = response.json()
session = data["data"]["session"]
print("Session closed:", session["id"])
print("Status:", session["status"])
Bash
curl -X POST https://bbre-solver-api.mydisct.com/session/close \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{"sessionId": "session_abc123def456"}'

Safe Session Close with Error Handling

In production applications, you should always wrap the session close call in error handling logic. The close operation can fail if the session has already been closed, if the session does not exist, or if there is a temporary server error. The following examples demonstrate a robust close pattern that handles all possible error scenarios gracefully and logs appropriate messages for debugging.

JavaScript
const axios = require("axios");

const API_BASE = "https://bbre-solver-api.mydisct.com";
const API_KEY = "YOUR_API_KEY";
const authHeaders = {
  "Content-Type": "application/json",
  "x-api-key": API_KEY
};

async function safeCloseSession(sessionId) {
  try {
    const response = await axios.post(
      API_BASE + "/session/close",
      { sessionId: sessionId },
      { headers: authHeaders }
    );
    console.log("Session", sessionId, "closed successfully");
    return { success: true, data: response.data };
  } catch (error) {
    if (error.response) {
      const errorCode = error.response.data.error?.code;
      if (errorCode === "SESSION_CLOSED") {
        console.log("Session", sessionId, "was already closed");
        return { success: true, alreadyClosed: true };
      }
      if (errorCode === "SESSION_NOT_FOUND") {
        console.log("Session", sessionId, "not found, may have expired");
        return { success: true, notFound: true };
      }
      console.error("Failed to close session:", errorCode);
      return { success: false, error: errorCode };
    }
    console.error("Network error closing session:", error.message);
    return { success: false, error: "NETWORK_ERROR" };
  }
}

safeCloseSession("session_abc123def456");
Python
import requests

API_BASE = "https://bbre-solver-api.mydisct.com"
API_KEY = "YOUR_API_KEY"

headers = {
    "Content-Type": "application/json",
    "x-api-key": API_KEY
}

def safe_close_session(session_id):
    try:
        response = requests.post(
            API_BASE + "/session/close",
            headers=headers,
            json={"sessionId": session_id}
        )

        if response.status_code == 200:
            print(f"Session {session_id} closed successfully")
            return {"success": True, "data": response.json()}

        error_data = response.json()
        error_code = error_data.get("error", {}).get("code", "UNKNOWN")

        if error_code == "SESSION_CLOSED":
            print(f"Session {session_id} was already closed")
            return {"success": True, "already_closed": True}

        if error_code == "SESSION_NOT_FOUND":
            print(f"Session {session_id} not found, may have expired")
            return {"success": True, "not_found": True}

        print(f"Failed to close session: {error_code}")
        return {"success": False, "error": error_code}

    except requests.exceptions.RequestException as e:
        print(f"Network error closing session: {e}")
        return {"success": False, "error": "NETWORK_ERROR"}

safe_close_session("session_abc123def456")

Complete Workflow with Session Close

The following example demonstrates the recommended pattern for using sessions: create a session, perform your workflow, and always close the session in a finally block. This ensures the session is closed regardless of whether the workflow succeeds or encounters an error. This pattern is the foundation of reliable BBRE session management and should be used in every production integration.

JavaScript
const axios = require("axios");

const API_BASE = "https://bbre-solver-api.mydisct.com";
const API_KEY = "YOUR_API_KEY";
const authHeaders = {
  "Content-Type": "application/json",
  "x-api-key": API_KEY
};

async function scrapeWithSession() {
  let sessionId = null;

  try {
    const createResponse = await axios.post(
      API_BASE + "/session/create",
      { mode: "passive", sensibility: "medium", timeout: 300 },
      { headers: authHeaders }
    );
    sessionId = createResponse.data.session.id;
    console.log("Session created:", sessionId);

    const loginResponse = await axios.post(
      API_BASE + "/session/request",
      {
        sessionId: sessionId,
        url: "https://example.com/api/login",
        method: "POST",
        body: { username: "myuser", password: "mypassword" }
      },
      { headers: authHeaders }
    );
    console.log("Login status:", loginResponse.data.data.task.result.statusCode);

    const dataResponse = await axios.post(
      API_BASE + "/session/request",
      {
        sessionId: sessionId,
        url: "https://example.com/api/data",
        method: "GET"
      },
      { headers: authHeaders }
    );
    console.log("Data fetched:", dataResponse.data.data.task.result.statusCode);

    return dataResponse.data.data.task.result.body;

  } finally {
    if (sessionId) {
      await axios.post(
        API_BASE + "/session/close",
        { sessionId: sessionId },
        { headers: authHeaders }
      ).catch(err => console.error("Failed to close session:", err.message));
      console.log("Session closed:", sessionId);
    }
  }
}

scrapeWithSession();
Python
import requests

API_BASE = "https://bbre-solver-api.mydisct.com"
API_KEY = "YOUR_API_KEY"

headers = {
    "Content-Type": "application/json",
    "x-api-key": API_KEY
}

session_id = None

try:
    create_response = requests.post(
        API_BASE + "/session/create",
        headers=headers,
        json={"mode": "passive", "sensibility": "medium", "timeout": 300}
    )
    session_id = create_response.json()["session"]["id"]
    print("Session created:", session_id)

    login_response = requests.post(
        API_BASE + "/session/request",
        headers=headers,
        json={
            "sessionId": session_id,
            "url": "https://example.com/api/login",
            "method": "POST",
            "body": {"username": "myuser", "password": "mypassword"}
        }
    )
    print("Login status:", login_response.json()["data"]["task"]["result"]["statusCode"])

    data_response = requests.post(
        API_BASE + "/session/request",
        headers=headers,
        json={
            "sessionId": session_id,
            "url": "https://example.com/api/data",
            "method": "GET"
        }
    )
    print("Data fetched:", data_response.json()["data"]["task"]["result"]["statusCode"])

finally:
    if session_id:
        try:
            requests.post(
                API_BASE + "/session/close",
                headers=headers,
                json={"sessionId": session_id}
            )
            print("Session closed:", session_id)
        except Exception as e:
            print("Failed to close session:", e)
Bash
SESSION_RESPONSE=$(curl -s -X POST https://bbre-solver-api.mydisct.com/session/create \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{"mode": "passive", "timeout": 300}')

SESSION_ID=$(echo $SESSION_RESPONSE | jq -r '.session.id')
echo "Session created: $SESSION_ID"

curl -s -X POST https://bbre-solver-api.mydisct.com/session/request \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d "{\"sessionId\": \"$SESSION_ID\", \"url\": \"https://example.com/api/data\", \"method\": \"GET\"}"

curl -s -X POST https://bbre-solver-api.mydisct.com/session/close \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d "{\"sessionId\": \"$SESSION_ID\"}"

echo "Session closed: $SESSION_ID"

Response Format

The session close endpoint returns a JSON response indicating whether the session was closed successfully. On success, the response includes the session ID and its updated status. On failure, the response includes an error code, a human-readable message, and additional details where applicable. The response always includes the "service": "MyDisct Solver BBRE" field to identify which service processed the request.

Success Response (200)

A successful session close returns the following structure. The session.id confirms which session was closed, and the session.status is always "closed" in a successful response. Once a session is closed, it cannot be reopened or reused. You must create a new session if you need to continue interacting with the target website.

JSON
{
  "success": true,
  "service": "MyDisct Solver BBRE",
  "data": {
    "session": {
      "id": "session_abc123def456",
      "status": "closed"
    }
  }
}
Field Type Description
success boolean Always true for successful responses.
service string Always "MyDisct Solver BBRE". Identifies the service that processed the request.
data.session.id string The unique session identifier that was closed. Matches the sessionId you sent in the request body.
data.session.status string The updated session status. Always "closed" for successful close operations.

Error Response Examples

When the session close operation fails, the API returns an error response with the appropriate HTTP status code, error code, and a descriptive message. The following examples show the most common error responses you may encounter when closing sessions.

400 - Session Already Closed

JSON
{
  "success": false,
  "service": "MyDisct Solver BBRE",
  "error": {
    "code": "SESSION_CLOSED",
    "message": "Session is already closed."
  }
}

400 - Session ID Required

JSON
{
  "success": false,
  "service": "MyDisct Solver BBRE",
  "error": {
    "code": "SESSION_ID_REQUIRED",
    "message": "Session ID is required.",
    "details": {
      "hint": "Session ID is returned when you create a session"
    }
  }
}

404 - Session Not Found

JSON
{
  "success": false,
  "service": "MyDisct Solver BBRE",
  "error": {
    "code": "SESSION_NOT_FOUND",
    "message": "Session not found."
  }
}

Error Codes

The following table lists all error codes that can be returned by the session close endpoint, along with their HTTP status codes, descriptions, and recommended solutions. Implementing proper error handling for each of these codes ensures your application can recover gracefully from any failure scenario. Note that some error codes like SESSION_CLOSED and SESSION_NOT_FOUND are not necessarily fatal errors in the context of session cleanup. If you are closing a session as part of cleanup logic, you can safely treat these as successful outcomes since the end result is the same: the session is no longer active and is not consuming your session slots.

HTTP Status Error Code Description Solution
400 SESSION_ID_REQUIRED The sessionId field is missing from the request body. The request validator rejects the request before it reaches the controller. Include the sessionId field in your JSON request body. The session ID is the session.id value returned by the POST /session/create endpoint.
400 SESSION_CLOSED The session has already been closed. This can happen if you call close twice on the same session, or if another part of your application already closed it. No action needed. The session is already in the desired state. In your error handling logic, treat this as a non-fatal condition and continue with your workflow. This is expected behavior when implementing retry logic for session cleanup.
401 API_KEY_REQUIRED No API key was provided in the request headers. Include your API key in the x-api-key or apikey header.
403 INVALID_API_KEY The provided API key is not valid or does not exist. Verify your API key in the MyDisct Solver dashboard. Ensure you are copying the complete key without extra spaces.
404 SESSION_NOT_FOUND No session with the provided ID exists for the authenticated user. This can happen if the session ID is incorrect, if the session was created by a different account, or if the session record has been removed from the system. Verify the session ID is correct and matches the value returned by POST /session/create. Ensure you are using the same API key that was used to create the session. If the session has expired and been cleaned up, no further action is needed.
500 SERVICE_ERROR An internal server error occurred while processing the session close request. This can happen if the BBRE engine encounters an error while releasing the browser context. Retry the request after a short delay (2-5 seconds). If the error persists, the session will eventually expire based on its timeout value. Contact support if the error continues across multiple sessions.

Node.js SDK Usage

The mydisctsolver-bbre Node.js SDK provides two convenient ways to close sessions. The BBREClient class has a closeSession() method that accepts a session ID and closes the session directly. Additionally, if you are using the BBRESession class for session-based workflows, the session object itself has a close() method that closes the session it represents. Both methods wrap the POST /session/close endpoint and handle authentication headers, request formatting, and response parsing automatically.

Close Session via BBREClient

Use the client.closeSession() method when you have a session ID stored as a string and want to close it directly through the client instance. This is useful when you are managing session IDs manually or when you need to close a session from a different part of your application than where it was created.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({
  apiKey: "YOUR_API_KEY"
});

async function closeWithClient() {
  const sessionId = "session_abc123def456";

  const result = await client.closeSession(sessionId);
  console.log("Session closed:", result.session.id);
  console.log("Status:", result.session.status);

  return result;
}

closeWithClient();

Close Session via BBRESession Object

When you create a session using the SDK's session management features, the returned BBRESession object has a built-in close() method. This is the most natural way to close sessions in SDK-based workflows because the session object already knows its own session ID and the client configuration needed to make the API call.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({
  apiKey: "YOUR_API_KEY",
  mode: "passive",
  sensibility: "medium"
});

async function workflowWithSessionClose() {
  const session = await client.createSession({ timeout: 300 });
  console.log("Session created:", session.sessionId);

  try {
    const loginResult = await session.request({
      url: "https://example.com/api/login",
      method: "POST",
      body: { username: "myuser", password: "mypassword" }
    });
    console.log("Login status:", loginResult.statusCode);

    const dataResult = await session.request({
      url: "https://example.com/api/data",
      method: "GET"
    });
    console.log("Data fetched:", dataResult.statusCode);

    return dataResult.body;

  } finally {
    await session.close();
    console.log("Session closed");
  }
}

workflowWithSessionClose();

Batch Close Multiple Sessions

If your application manages multiple sessions simultaneously, you may need to close several sessions at once during cleanup. The following example demonstrates how to close multiple sessions in parallel using Promise.allSettled(), which ensures all close attempts complete even if some fail. This is particularly useful during application shutdown or when implementing a session pool reset.

JavaScript
const BBREClient = require("mydisctsolver-bbre");

const client = new BBREClient({
  apiKey: "YOUR_API_KEY"
});

async function closeAllSessions(sessionIds) {
  const closePromises = sessionIds.map(id =>
    client.closeSession(id)
      .then(() => ({ id, status: "closed" }))
      .catch(err => ({ id, status: "failed", error: err.message }))
  );

  const results = await Promise.allSettled(closePromises);

  results.forEach(result => {
    if (result.status === "fulfilled") {
      const data = result.value;
      console.log("Session", data.id, ":", data.status);
    }
  });

  return results;
}

const activeSessions = [
  "session_abc123",
  "session_def456",
  "session_ghi789"
];

closeAllSessions(activeSessions);

The SDK methods throw an error if the API returns an error response. For cleanup scenarios, wrap the close call in a try/catch block and treat SESSION_CLOSED and SESSION_NOT_FOUND errors as non-fatal conditions. For more details on the SDK session management methods, see the Session Management documentation.

Best Practices

Always Use try/finally for Session Cleanup

The most important pattern for BBRE session management is wrapping your workflow in a try/finally block where the session close call lives in the finally section. This guarantees the session is closed regardless of whether your workflow succeeds, throws an error, or encounters an unexpected exception. Without this pattern, any error in your workflow leaves the session open and consuming one of your 10 active session slots. Over time, leaked sessions accumulate and eventually trigger SESSION_LIMIT_REACHED errors that block new session creation. In JavaScript, use try { ... } finally { await closeSession(); }. In Python, use try: ... finally: close_session(). This single pattern prevents the majority of session management issues that developers encounter in production.

Treat SESSION_CLOSED and SESSION_NOT_FOUND as Success in Cleanup

When closing sessions as part of cleanup logic (in finally blocks, shutdown handlers, or error recovery), do not treat SESSION_CLOSED and SESSION_NOT_FOUND errors as failures. Both of these conditions mean the session is no longer active, which is exactly the outcome you want from a close operation. A session might already be closed if another part of your application closed it, or if a retry mechanism triggered a duplicate close call. A session might not be found if it expired and was cleaned up by the system. In both cases, the session is not consuming your session slots, so the cleanup objective is achieved. Only treat SERVICE_ERROR and network errors as genuine failures that warrant retry logic.

Close Sessions Immediately After Workflow Completion

Do not wait for sessions to expire naturally. As soon as your workflow finishes extracting the data or completing the interaction you need, close the session immediately. Every second a session remains open after your workflow completes is a wasted session slot that could be used for another workflow. This is especially important in high-throughput applications where you are processing many concurrent workflows. If you create sessions with a 300-second timeout but your workflows typically complete in 30 seconds, you are wasting 270 seconds of session slot capacity per workflow by not closing sessions promptly. Multiply that by dozens of concurrent workflows and the impact on your throughput becomes significant.

Implement Graceful Shutdown with Session Cleanup

Register shutdown handlers in your application that close all active sessions when the process is terminating. In Node.js, listen for SIGTERM and SIGINT signals and close all tracked sessions before exiting. In Python, use the atexit module or signal handlers. Keep a list of active session IDs in your application state so you can iterate through them during shutdown. Use Promise.allSettled() in JavaScript or equivalent parallel execution in Python to close all sessions concurrently, which minimizes the shutdown time. This prevents orphaned sessions from accumulating when your application restarts frequently, such as during deployments or auto-scaling events.

Common Issues

Issue 1: SESSION_CLOSED Error When Closing a Session

Problem

You receive a 400 SESSION_CLOSED error when trying to close a session. This typically happens when your application has multiple code paths that attempt to close the same session, or when a retry mechanism sends the close request more than once.

Solution: This error is not a problem in most cases. It simply means the session was already closed before your close request arrived. In your error handling logic, check for the SESSION_CLOSED error code and treat it as a successful outcome. The session is no longer active and is not consuming your session slots, which is the desired result. If you want to prevent this error entirely, you can track session state locally in your application and skip the close call if you have already recorded a successful close for that session ID. However, the simpler approach is to always attempt the close and handle the SESSION_CLOSED response gracefully.

Issue 2: SESSION_NOT_FOUND When Closing a Session

Problem

You receive a 404 SESSION_NOT_FOUND error when trying to close a session that you believe should exist. This can be confusing because you have a valid session ID that was returned by the session creation endpoint.

Solution: There are three common causes for this error. First, the session ID might be incorrect due to a typo or a variable assignment error in your code. Double-check that the session ID you are sending matches exactly the value returned by POST /session/create. Second, you might be using a different API key than the one used to create the session. Sessions are scoped to the account that created them, so you must use the same API key for both creation and closure. Third, the session record may have been removed from the system after expiration. In cleanup scenarios, treat SESSION_NOT_FOUND as a non-fatal condition since the session is not consuming your session slots regardless of the reason it was not found.

Issue 3: Leaked Sessions Causing SESSION_LIMIT_REACHED

Problem

You frequently encounter 429 SESSION_LIMIT_REACHED errors when creating new sessions, even though your application should not have 10 active sessions at any given time. This indicates that sessions are being leaked, meaning they are created but never closed.

Solution: Session leaks are almost always caused by missing close calls in error paths. Review your code and ensure every code path that creates a session also closes it, including error handling paths. The most reliable fix is to use the try/finally pattern described in the Best Practices section above. Additionally, use the POST /account/sessions endpoint to list your currently active sessions and close any that are no longer needed. As a temporary workaround, you can close leaked sessions manually using this endpoint with each session ID. For a permanent fix, audit your codebase and wrap every session creation in a try/finally block that guarantees the session is closed when the workflow ends.