Flask

Sign Ticketping identity tokens in Flask with PyJWT and Flask-Login.

You’ll add a blueprint with one POST route. This example uses Flask-Login; with another auth extension, swap in its decorator and current user.

Install PyJWT

bash
pip install PyJWT

Set the secret

Get the identity secret from Settings → API → Identity secret and set it in your server’s environment. It’s the same value everywhere.

bash
TICKETPING_IDENTITY_SECRET=tpis_...

Add the route

ticketping.py:

python
import os
import time

import jwt
from flask import Blueprint
from flask_login import current_user, login_required

ticketping = Blueprint("ticketping", __name__)


@ticketping.post("/api/ticketping-token")
@login_required
def ticketping_token():
    claims = {"sub": str(current_user.id), "exp": int(time.time()) + 300}
    if current_user.email:
        claims["email"] = current_user.email
    if current_user.name:
        claims["name"] = current_user.name

    token = jwt.encode(claims, os.environ["TICKETPING_IDENTITY_SECRET"], algorithm="HS256")
    return token, 200, {"Content-Type": "text/plain"}

Register the blueprint where you create the app:

python
from ticketping import ticketping

app.register_blueprint(ticketping)

Change current_user.name to match your user model.

@login_required answers 401 when nobody is signed in, unless you’ve set a login_view. Then it redirects to your login page, and fetch would return that page’s HTML as the “token”. Make this blueprint answer 401 instead:

python
login_manager.blueprint_login_views = {"ticketping": None}

If you use Flask-WTF’s CSRFProtect, either send the CSRF token from getToken (below), or exempt this route with csrf.exempt(ticketping). The route only signs a token for the user who’s already signed in, and its response can’t be read cross-origin.

Call it from your templates

html
{% if current_user.is_authenticated %}
<script>
  window.Ticketping ||= (...args) => (Ticketping.q ||= []).push(args)

  Ticketping('identify', {
    userId: {{ current_user.id|string|tojson }},
    email: {{ current_user.email|tojson }},
    name: {{ current_user.name|tojson }},
    getToken: async () => {
      const res = await fetch('/api/ticketping-token', {
        method: 'POST',
        headers: { 'X-CSRFToken': '{{ csrf_token() }}' }
      })
      if (!res.ok) throw new Error(`Ticketping token request failed (${res.status})`)
      return res.text()
    }
  })
</script>
{% endif %}
<script src="https://widget.ticketping.com/v2/loader.js" data-key="pk_..." async></script>

Drop the X-CSRFToken header if you don’t use Flask-WTF. Call Ticketping('logout') when the user signs out.

Check that it works

  1. Sign in on localhost and run await (await fetch('/api/ticketping-token', { method: 'POST' })).text() in the browser console (add the CSRF header if you use it).
  2. Paste the token into the token validator under Settings → API → Identity secret. It shows the claims, or says exactly what to fix.
  3. Reload and send a message. The dashboard shows it with the user’s name and a Verified badge.

Copy prompt for your AI coding agent

prompt
Add Ticketping identity verification (chat widget v2) to this Flask app.

Docs index: https://ticketping.com/llms.txt
This page as Markdown: https://ticketping.com/docs/identity-flask.md

1. Add PyJWT to the dependencies.
2. Create the ticketping blueprint exactly as on the docs page and register it: POST /api/ticketping-token,
   protected by this app's login decorator, returning jwt.encode({"sub": str(current_user.id), "exp": int(time.time()) + 300,
   plus email and name only when non-empty}, os.environ["TICKETPING_IDENTITY_SECRET"], algorithm="HS256") as text/plain.
3. Add TICKETPING_IDENTITY_SECRET= to the env example file. Never commit the value.
4. In the base template, for signed-in users only, add the queue stub and Ticketping('identify', { userId, email, name, getToken })
   with getToken POSTing to the route (with the CSRF header if Flask-WTF is used) and returning res.text().
   Add the loader script with data-key="pk_..." and ask me for the publishable key. Call Ticketping('logout') on sign-out.
5. Tell me how to verify with the token validator at Settings → API → Identity secret.