This document lists the HTTP endpoints tenant applications (external apps) call to integrate with the ticket system. It covers both SSO redirect tokens and the JWT login flow, required parameters, authentication expectations, and quick curl examples.
Important: the platform supports two routing modes:
Always use HTTPS in staging/production.
Purpose: central platform issues an encrypted redirect token which the user browser is redirected to, allowing the platform to complete SSO flow.
GET https://ticket.<tenant-domain>/auth/callback?token=<ENCRYPTED_TOKEN>GET https://<host>/<tenant_slug>/auth/callback?token=<ENCRYPTED_TOKEN>AuthRedirectService (server-side) and issues a 302 redirect to the callback URL above.token — encrypted payload (handled by platform services). The callback will validate, create/find user, and create a session.Quick example (platform-side redirect):
Location: https://ticket.yourtenant.com/auth/callback?token=<ENCRYPTED_TOKEN>
Notes:
Purpose: external tenant app generates a short-lived HMAC-SHA256-signed token that the platform accepts to create a session for a user.
Endpoint: GET or POST to:
https://ticket.<tenant-domain>/api/jwt/loginhttps://<host>/<tenant_slug>/api/jwt/loginRequired parameters (query or form):
token (string) — the signed token. Supports two formats:
header.payload.signature (3-parts, standard libraries)base64(payload).signature (2-parts, legacy)tenant_slug (string) — tenant slug (required unless host/subdomain resolution guaranteed)intended (string, optional) — URL to redirect user to after session created (e.g. /tickets/123)Token payload requirements (JSON encoded then base64):
email (string) — user emailname (string) — full nameiat (int) — issued at (unix timestamp)exp (int) — expiry (unix timestamp; short TTL recommended, e.g. iat + 120)jti (string, recommended) — unique ID for replay protectionAuth: token itself authenticates the user flow; server-to-server API calls use X-Tenant-API-Token or v2 X-API-Key/X-API-Secret as appropriate.
Example (curl GET redirect-style):
curl -i "https://ticket.yourtenant.com/api/jwt/login?token=<TOKEN>&tenant_slug=yourtenant&intended=%2Ftickets%2F5"
Example (curl POST):
curl -X POST "https://ticket.yourtenant.com/api/jwt/login" \
-d "token=<TOKEN>" \
-d "tenant_slug=yourtenant" \
-d "intended=/tickets/5"
Notes:
tenant_slug can be omitted — but passing tenant_slug is recommended for determinism.jwt_secret (Blue Banner in Settings) and checks iat/exp and JTI replay cache.These are tenant-scoped API endpoints (use tenant API token or JWT-based auth depending on your integration):
/api/tickets — Create a ticket. Body: title, description (or description becomes first reply), category_id, etc./api/tickets — List tickets for tenant/api/tickets/{id} — Get ticket/api/tickets/{id} — Update ticket/api/tickets/{id} — Delete ticket/api/categories — List categories/api/tenant — Return tenant info (configuration)Authentication methods for these APIs:
X-Tenant-API-Token header — tenant API token (server-to-server)/api/v2/* use X-API-Key + X-API-Secret (Amber Banner in Settings). See AuthenticateTenantApiV2 middleware.POST /api/auth/redirect — Request platform to generate an encrypted redirect token and return a 302 to the platform callback. Use when the external system asks the platform to generate the encrypted redirect token. The body must include the tenant slug.GET /api/auth/callback — Platform endpoint that processes encrypted redirect tokens (used in redirect flow described in section 1).POST /api/sso/token and POST /api/sso/verify — Supporting endpoints used by SSO workflows (internal or partner integrations).Purpose: When a user logs out of the tenant application, notify the ticket system so the user's ticket session is also ended on their next request.
POST /api/auth/logoutX-API-Key + X-API-Secret headers (from Settings > API)Request body (one of):
{ "email": "user@example.com" }
{ "external_user_id": "12345" }
At least one of email or external_user_id must be provided.
Quick example (curl):
curl -X POST "https://ticket.yourtenant.com/api/auth/logout" \
-H "Content-Type: application/json" \
-H "X-API-Key: tk_your_api_key" \
-H "X-API-Secret: your_api_secret" \
-d '{"email": "user@yourtenant.com"}'
Response (always 200 to prevent user enumeration):
{ "success": true, "message": "Logout processed" }
How it works:
POST /api/auth/logout with the user's emailforce_logout:{tenant_id}:{user_id}VerifyTenantSessionSync middleware detects the flagNotes:
session.lifetime + 5 minutes (auto-cleanup)user are affected (admins and agents are never force-logged-out)ExternalAuthSessionService) which has been removed/api/v2/* and require X-API-Key + X-API-Secret headers for authentication. Use these for programmatic tenant operations when available.This is not an endpoint on the ticket system — it is an endpoint you must implement in your application. The ticket system calls it when a staff member uses the "File Ticket for User" feature to create a ticket for someone who doesn't yet have a local account. The resulting ticket is labelled "Filed for [user]" in the conversation thread.
Purpose: Confirm that a given email address belongs to a registered member of the tenant application before provisioning them and creating a ticket for them.
Set both the URL and verification token in the master Tenant edit form:
| Field | Value |
|---|---|
user_verification_url |
https://yourapp.com/api/verify-member |
verification_token |
your_shared_secret_here |
The field accepts any HTTPS URL. It is called synchronously at ticket creation time (10 second timeout).
POST {user_verification_url}
Authorization: Bearer {tenant.verification_token}
Content-Type: application/json
Accept: application/json
{
"email": "user@example.com"
}
User exists (200 OK):
{
"exists": true,
"user": {
"name": "Jane Doe",
"email": "user@example.com"
}
}
User does not exist (200 OK):
{
"exists": false
}
Always return
200 OK. Non-2xx responses are treated as errors and presented to the staff member as "unable to verify".
| Scenario | Outcome |
|---|---|
| User exists in ticket system locally | Ticket created immediately, no external call made |
User not local, user_verification_url not set |
Error: staff is informed the user must already be registered |
User not local, external returns exists: false |
Error: "This user is not a member of the tenant application" |
User not local, external returns exists: true |
User auto-provisioned (role user, random password), ticket created, email sent to user |
| External endpoint unreachable or returns non-2xx | Error surfaced to staff member, ticket not created |
Once a ticket is filed for a user, the ticket system sends them an email with:
The email uses the tenant's configured SMTP settings (or falls back to global settings).
Authorization: Bearer token matches your configured verification secret401 or any non-2xx status to reject unauthorized requestsname and email are needed in the responseQuick example (curl, for testing):
curl -X POST "https://yourapp.com/api/verify-member" \
-H "Authorization: Bearer your_shared_verification_secret" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"email": "user@example.com"}'
jti to protect against replay.tenant_slug with calls unless you can guarantee call originates from the tenant subdomain.php artisan serve with slug path: http://127.0.0.1:8000/{tenant_slug}/api/jwt/login.If you want, I can also:
docs/examples/jwt_login.sh script with token generation + curl examples for local testing.File: docs/TENANT_API_ENDPOINTS.md