Skip to main content

Overview

This endpoint marks a chat session as closed. Closed sessions are archived and no longer receive new messages. Use this when:
  • A user ends a conversation
  • A support ticket is resolved
  • A session is inactive for an extended period
  • You want to create a new session for the same user (fresh context)
Closing a session is idempotent: closing an already-closed session returns success.

Authentication

Requires API key in the X-API-Key header:
X-API-Key: <YOUR_API_KEY>

Request body

session_id
string
required
The session ID to close.

Request example

curl --request POST \
  --url "https://api.uppzy.com/api/v1/m2m/sites/<SITE_ID>/chat/session/close" \
  --header "X-API-Key: <YOUR_API_KEY>" \
  --header "Content-Type: application/json" \
  --data '{
    "session_id": "user-123-web"
  }'

Response schema

status
string
Always ok on success.

Response example

{
  "status": "ok"
}

Error responses

400 Bad Request

Missing or invalid session ID.
{
  "error": "session_id is required"
}

401 Unauthorized

API key is missing, invalid, expired, or revoked.
{
  "error": "invalid_api_key"
}

403 Forbidden

The API key’s plan does not include M2M API access.
{
  "error": "api_access_not_available_on_plan"
}

404 Not Found

The site does not exist.
{
  "error": "site not found"
}

500 Internal Server Error

An unexpected error occurred.

Implementation tips

Idempotency

Closing an already-closed session returns success:
// First close
await fetch(...POST /chat/session/close...);
// Returns: { status: "ok" }

// Second close (same session)
await fetch(...POST /chat/session/close...);
// Returns: { status: "ok" } (no error)

When to close a session

Close sessions in these scenarios:
  1. User-initiated: User clicks “End conversation” or closes the chat widget
  2. Time-based: Close sessions inactive for > 24 hours
  3. Status-based: Close sessions when a support ticket is resolved
  4. Context shift: Start a new session when switching topics
// Example: close after 24 hours of inactivity
async function closeInactiveSessions(siteId, olderThanHours = 24) {
  // Get all sessions
  const sessionsResp = await fetch(
    `https://api.uppzy.com/api/v1/m2m/sites/${siteId}/sessions`,
    {
      headers: { "X-API-Key": process.env.UPPZY_API_KEY },
    }
  );
  const { sessions } = await sessionsResp.json();

  // Filter inactive sessions
  const now = new Date();
  const inactiveSessions = sessions.filter((session) => {
    if (session.closed_at) return false; // Already closed
    const lastActivity = new Date(session.updated_at);
    const hoursSinceActivity = (now - lastActivity) / (1000 * 60 * 60);
    return hoursSinceActivity > olderThanHours;
  });

  // Close them
  for (const session of inactiveSessions) {
    await fetch(
      `https://api.uppzy.com/api/v1/m2m/sites/${siteId}/chat/session/close`,
      {
        method: "POST",
        headers: {
          "X-API-Key": process.env.UPPZY_API_KEY,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ session_id: session.id }),
      }
    );
  }

  console.log(`Closed ${inactiveSessions.length} inactive sessions`);
}

Starting a fresh session after closing

When you close a session and want the user to continue, use a new session ID:
async function restartConversationWithFreshSession(
  siteId,
  oldSessionId,
  userEmail
) {
  // Close the old session
  await fetch(
    `https://api.uppzy.com/api/v1/m2m/sites/${siteId}/chat/session/close`,
    {
      method: "POST",
      headers: {
        "X-API-Key": process.env.UPPZY_API_KEY,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ session_id: oldSessionId }),
    }
  );

  // Start fresh with a new session ID
  const newSessionId = `${userEmail}-${Date.now()}`;
  const response = await fetch(
    `https://api.uppzy.com/api/v1/m2m/sites/${siteId}/chat`,
    {
      method: "POST",
      headers: {
        "X-API-Key": process.env.UPPZY_API_KEY,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        session_id: newSessionId,
        message: "Hi, I'm starting a new conversation.",
        email: userEmail,
      }),
    }
  );

  return response.json();
}

Batch closing multiple sessions

Close multiple sessions efficiently:
async function closeMultipleSessions(siteId, sessionIds) {
  const promises = sessionIds.map((sessionId) =>
    fetch(
      `https://api.uppzy.com/api/v1/m2m/sites/${siteId}/chat/session/close`,
      {
        method: "POST",
        headers: {
          "X-API-Key": process.env.UPPZY_API_KEY,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ session_id: sessionId }),
      }
    )
  );

  const results = await Promise.all(promises);
  const successCount = results.filter((r) => r.ok).length;

  console.log(`Successfully closed ${successCount}/${sessionIds.length} sessions`);
}

Marking session state in your database

Track which sessions you’ve closed:
async function closeSessionAndLog(siteId, sessionId, userId) {
  // Close on Uppzy
  const response = await fetch(
    `https://api.uppzy.com/api/v1/m2m/sites/${siteId}/chat/session/close`,
    {
      method: "POST",
      headers: {
        "X-API-Key": process.env.UPPZY_API_KEY,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ session_id: sessionId }),
    }
  );

  if (response.ok) {
    // Update your database
    await db.query(
      `UPDATE chat_sessions SET closed_at = NOW() WHERE session_id = ?`,
      [sessionId]
    );
  }
}