Skip to main content
Context Links are buttons in the conversation sidebar that open external URLs with contact and conversation details filled in. Agents click them to jump to CRMs, billing systems, or internal dashboards without copy-pasting identifiers.

URL Template Variables

These placeholders are replaced with the current contact’s details when an agent clicks the link.
VariableDescription
{{email}}Contact’s email
{{phone}}Contact’s phone number
{{phone_country_code}}Contact’s phone country code
{{external_user_id}}Contact’s external user ID
{{contact_id}}Contact’s internal Libredesk ID
{{first_name}}Contact’s first name
{{last_name}}Contact’s last name
{{conversation_uuid}}UUID of the current conversation
{{token}}Encrypted token containing all fields (requires secret)
All values except {{contact_id}} and {{conversation_uuid}} are URL-encoded automatically.

Examples

Simple lookup by email:
https://crm.example.com/contacts?email={{email}}
Multiple parameters:
https://billing.example.com/customer?ext_id={{external_user_id}}&email={{email}}
Internal dashboard with conversation context:
https://dashboard.internal/lookup?contact={{contact_id}}&conv={{conversation_uuid}}
Secure integration with encrypted token:
https://api.example.com/auth/libredesk?token={{token}}
The receiving system decrypts the token to get all contact and agent fields in one payload, without exposing them in the URL.

Encrypted Token

When you use {{token}}, Libredesk generates an AES-256-GCM encrypted, time-limited token containing all the above fields plus agent_id, agent_email, iat, and exp. The receiving system decrypts it with the shared secret.

Decrypting the Token

import base64, json, time
from cryptography.hazmat.primitives.ciphers.aead import AESGCM

def decrypt_context_token(token, secret):
    raw = base64.b64decode(token)
    nonce = raw[:12]
    ciphertext = raw[12:]

    aesgcm = AESGCM(secret.encode('utf-8'))
    plaintext = aesgcm.decrypt(nonce, ciphertext, None)
    return json.loads(plaintext)

# Usage
secret = "your-32-character-shared-secret!"  # exactly 32 characters
payload = decrypt_context_token(token_from_url, secret)

if payload["exp"] < time.time():
    raise ValueError("Token has expired")

print(payload["email"], payload["conversation_uuid"])