Ticketping Docs

Authentication

Identify authenticated user with JWT

By default, the Ticketping widget can be embedded without authentication.
If you want to associate chats with logged-in users from your product, you’ll need to issue a JWT token for each user session.

Steps

1. Generate a JWT Secret

  • Go to Ticketping dashboard API Keys.
  • Click New API Key.
  • This will generate a pair of API key and JWT Secret.
  • Copy JWT Secret and keep it safe. This secret is used to sign all JWTs issued by your server.

Never expose this secret in your frontend code. It should only be stored on your backend.

2. Create an API in your backend codebase

You’ll need an endpoint that your frontend chat widget can call to fetch a signed JWT for the current user.

The JWT must include some user identifiers and have a short expiration (we recommend 5 minutes).

FieldRequiredDescription
external_idUnique user ID in your system
emailUser’s email address
display_nameOptionalFriendly name to show in Ticketping
expExpiration timestamp (short-lived recommended)
import express from "express";
import jwt from "jsonwebtoken";

const app = express();

// Protect this route with your own authentication middleware
app.get("/api/ticketping/chat-jwt", (req, res) => {
  const user = req.user; // Assume you set this via auth middleware

  const payload = {
    external_id: user.id,
    email: user.email,
    display_name: user.name || user.email.split("@")[0],
    exp: Math.floor(Date.now() / 1000) + 60 * 5, // expires in 5 min
  };

  const token = jwt.sign(payload, process.env.TICKETPING_JWT_SECRET);

  res.json({ jwt: token });
});

3. Pass the JWT to the widget

On your frontend, call your new API and provide the token when initializing the widget via userJWT param:

window.TicketpingChat.init({
    appId: 'your-app-id',
    teamSlug: 'your-team-slug',
    teamLogoIcon: 'cdn-link-to-your-logo-square',
    userJWT: 'jwt-encoded-string-returned-by-your-API'
});

Examples in specific frameworks

import React, { useEffect, useRef, useState } from 'react';
import TicketpingChat from '@ticketping/chat-widget/react';

const myTheme = {
  primaryColor: '#007BFF',
  primaryHover: '#0056b3',
  textPrimary: '#111827',
  textSecondary: '#374151',
  textMuted: '#6b7280',
  background: '#ffffff',
  backgroundSecondary: '#f3f4f6',
  backgroundTertiary: '#e5e7eb',
};

// helper function to fetch JWT
async function fetchJwt() {
  try {
    const res = await fetch('/api/ticketping/chat-jwt', { credentials: 'include' });
    if (res.ok) {
      const { jwt } = await res.json();
      return jwt || '';
    }
  } catch (err) {
    console.error('Failed to fetch JWT:', err);
  }
  return '';
}

function App() {
  const chatRef = useRef();
  const [jwtToken, setJwtToken] = useState(null);
  const [jwtLoaded, setJwtLoaded] = useState(false);

  useEffect(() => {
    fetchJwt().then(token => {
      setJwtToken(token);
      setJwtLoaded(true);
    });
  }, []);

  return (
    <div>
      <h1>My App</h1>

      {jwtLoaded && (
        <TicketpingChat
          ref={chatRef}
          appId="your-app-id"
          teamSlug="your-team-slug"
          teamLogoIcon="cdn-link-to-your-logo-square"
          theme={myTheme}
          userJWT={jwtToken}
        />
      )}
    </div>
  );
}

export default App;

Security Notes

  • Always sign JWTs on your backend using the secret from the dashboard.
  • Keep expiration short. The widget will request a fresh token as needed.
  • Do not expose your JWT secret in frontend code or version control.