Ticketer Management
Ticketers connect your project to external ticket systems. The Weni CLI lets you create and configure generic ticketers from a YAML definition file, so agents and flows can open, forward, close, and reopen tickets through a partner HTTP service.
What are Ticketers?
A ticketer is the platform integration that routes ticket operations between VTEX CX and an external system. When a flow opens a ticket, the platform calls your partner service. When an agent replies or closes a ticket in the partner UI, the partner sends webhooks back to the platform.
The generic ticketer type uses a documented HTTP contract: any service that implements the required endpoints can be registered without custom Mailroom code.
Ticketer Types
Currently, the Weni CLI supports the following ticketer type:
- generic: HTTP-based integration with a partner ticketer service (open, forward, close, reopen, and history endpoints).
Creating a Ticketer
To create a new ticketer, you need to:
- Create a ticketer definition file in YAML format
- Have a project selected (use
weni project use <project_uuid>) - Run the ticketer creation command
Command
Arguments:
ticketer_definition_file: Path to the YAML file containing your ticketer configuration
Ticketer Definition Structure
A minimal ticketer definition (default HTTP contract, no custom templates):
ticketers:
- name: "Generic Ticketer Integration"
ticketer_type: "generic"
config:
base_url: "https://your-ticketer-host"
api_token: "<API_TOKEN>"
skip_webhook_hmac: "yes"
project_name: "my project"
route_open: "/v1/tickets"
route_forward: "/v1/tickets/{external_id}/messages"
route_close: "/v1/tickets/{external_id}/close"
route_reopen: "/v1/tickets/{external_id}/reopen"
route_history: "/v1/tickets/{external_id}/history"
route_history_message: "/v1/tickets/{external_id}/messages"
Only the first item in the ticketers array is used per command execution.
Configuration Fields
Root Fields
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Display name of the ticketer (max 100 characters) |
ticketer_type |
string | Yes | Type of ticketer. Currently supports: generic |
config |
object | Yes | Ticketer configuration object |
Config Fields — credentials and metadata
| Field | Type | Required | Description |
|---|---|---|---|
base_url |
string | Yes | Base URL of the partner ticketer service (must start with http:// or https://) |
api_token |
string | Yes | Bearer token the platform uses when calling the partner service |
webhook_secret |
string | Conditional | Secret used to verify inbound webhooks from the partner. Required unless skip_webhook_hmac is enabled |
skip_webhook_hmac |
string | No | Set to true, 1, or yes to skip webhook HMAC verification |
project_uuid |
string | No | Project UUID sent in ticket metadata. Auto-filled from the selected project when empty or omitted |
project_name |
string | No | Project name sent in ticket metadata |
Config Fields — routes
| Field | Type | Required | Description |
|---|---|---|---|
route_open |
string | No | Override for the open-ticket endpoint. Default: /v1/tickets |
route_forward |
string | No | Override for forwarding messages. Default: /v1/tickets/{external_id}/messages |
route_close |
string | No | Override for closing tickets. Default: /v1/tickets/{external_id}/close |
route_reopen |
string | No | Override for reopening tickets. Default: /v1/tickets/{external_id}/reopen |
route_history |
string | No | Override for batch history. Default: /v1/tickets/{external_id}/history |
route_history_message |
string | No | Override for one-by-one history. Default: same as route_forward (/v1/tickets/{external_id}/messages) |
Config Fields — conversation history
| Field | Type | Required | Description |
|---|---|---|---|
history_mode |
string | No | How history is sent after open: batch (default) or one_by_one |
history_batch_size |
string | No | Max messages per batch request when history_mode=batch. Default: 50 |
history_mode |
Endpoint used | Payload shape |
|---|---|---|
batch |
route_history |
HistoryRequest with a messages array |
one_by_one |
route_history_message / route_forward |
One MessageRequest per message (same as forward) |
Config Fields — payload templates
Optional Go text/template strings that customize request or response bodies. When a template is absent or empty, the platform uses the default HTTP contract.
Helpers available in templates: json (serialize a value as JSON) and toString.
Prefer {{json .field}} for strings and nested objects so quotes, newlines, and null values stay valid JSON. If you expand objects field-by-field without json, keep metadata.webhook_base_url in open_template — the partner needs it to send agent replies back to the platform.
| Field | Direction | Description |
|---|---|---|
open_template |
Platform → Ticketer | Replaces the default open-ticket request body |
open_response_template |
Platform ← Ticketer | Maps the partner open response to {external_id, status, created_at} |
forward_template |
Platform → Ticketer | Replaces the default forward-message request body |
forward_response_template |
Platform ← Ticketer | Maps the partner forward response to {message_external_id, status} |
close_template |
Platform → Ticketer | Replaces the default close-ticket request body |
close_response_template |
Platform ← Ticketer | Maps the partner close response to {status} |
history_template |
Platform → Ticketer | Replaces the history request body (batch or one_by_one context) |
history_response_template |
Platform ← Ticketer | Maps the partner history response to {status, messages_received} |
messages_template |
Ticketer → Platform | Maps the inbound agent-message webhook body to the standard envelope |
messages_response_template |
Ticketer ← Platform | Replaces the success response returned to the partner for agent messages |
tickets_close_template |
Ticketer → Platform | Maps the inbound close webhook body to the standard envelope |
tickets_close_response_template |
Ticketer ← Platform | Replaces the success response returned to the partner for close webhooks |
All config values must be strings.
Integration Flow
1. Platform opens ticket → POST {base_url}{route_open}
2. Partner returns → 201 { external_id }
3. Platform sends history → batch: POST {base_url}{route_history}
one_by_one: POST {base_url}{route_history_message} (per message)
4. Platform forwards new message → POST {base_url}{route_forward}
5. Agent replies in partner → POST {webhook_base_url}/messages
6. Agent closes in partner → POST {webhook_base_url}/tickets/close
On ticket open, the platform includes metadata.webhook_base_url so the partner knows where to send inbound events.
Example: Creating a Generic Ticketer
Step 1: Prepare the partner service
Run your ticketer service and copy the credentials it exposes (for example, from server logs or a settings screen):
API_TOKEN— used inconfig.api_tokenWEBHOOK_SECRET— used inconfig.webhook_secret
For local development, expose the service with a public URL (for example, ngrok) and use that URL as base_url.
Step 2: Create the ticketer definition file
Minimal (default payloads and routes):
ticketers:
- name: "Generic Ticketer Integration"
ticketer_type: "generic"
config:
base_url: "https://your-ticketer-host"
api_token: "your-api-token"
skip_webhook_hmac: "yes"
project_name: "my org"
With identity templates (custom templates that recreate the default contract). Useful to validate template wiring without changing payload shape:
ticketers:
- name: "Generic Ticketer (equivalent templates)"
ticketer_type: "generic"
config:
base_url: "https://your-ticketer-host"
api_token: "your-api-token"
skip_webhook_hmac: "yes"
history_mode: "batch"
history_batch_size: "50"
open_template: |-
{"ticket_id":{{json .ticket_id}},"topic":{{json .topic}},"contact":{{json .contact}},"body":{{json .body}},"assignee":{{json .assignee}},"metadata":{{json .metadata}},"opened_at":{{json .opened_at}}}
open_response_template: |-
{"external_id":{{json .external_id}},"status":{{json .status}},"created_at":{{json .created_at}}}
forward_template: |-
{"ticket_id":{{json .ticket_id}},"external_id":{{json .external_id}},"message_id":{{json .message_id}},"direction":{{json .direction}},"sender":{{json .sender}},"text":{{json .text}},"attachments":{{json .attachments}},"metadata":{{json .metadata}},"sent_at":{{json .sent_at}}}
# … remaining templates (close, history, messages, tickets_close) follow the same pattern
History one-by-one (each history message posted to the forward endpoint):
ticketers:
- name: "Generic Ticketer (history one-by-one)"
ticketer_type: "generic"
config:
base_url: "https://your-ticketer-host"
api_token: "your-api-token"
skip_webhook_hmac: "yes"
history_mode: "one_by_one"
route_history_message: "/v1/tickets/{external_id}/messages"
# Same shape as forward_template (MessageRequest per message)
history_template: |-
{"ticket_id":{{json .ticket_id}},"external_id":{{json .external_id}},"message_id":{{json .message_id}},"direction":{{json .direction}},"sender":{{json .sender}},"text":{{json .text}},"attachments":{{json .attachments}},"metadata":{{json .metadata}},"sent_at":{{json .sent_at}}}
# Partner usually replies with a forward-style body; map it to the history envelope
history_response_template: |-
{"status":"history_received","messages_received":1}
Step 3: Ensure you have a project selected
Step 4: Create the ticketer
On success, the CLI displays the ticketer name and UUID.
Best Practices
- Match routes to your partner API: If you override
route_*fields, ensure they match the endpoints your service actually exposes - Secure your credentials: Never commit ticketer definition files with real tokens to version control
- Use environment-specific files: Maintain separate definitions for development, staging, and production
- Align HMAC settings: If the partner runs with
SKIP_WEBHOOK_HMAC=true, setskip_webhook_hmac: "true"in the ticketer config as well - Preserve
webhook_base_urlin custom open templates: When usingopen_template, include the fullmetadataobject (for example with{{json .metadata}}) so agent replies can reach the platform - Prefer
{{json …}}in templates: Avoid breaking JSON when values contain quotes, newlines, or are null - Test the HTTP contract: Validate open, history, forward, close, reopen, and webhook flows before using the ticketer in production flows
Common Use Cases
- Custom support desks: Connect flows to an in-house ticketing UI
- Partner integrations: Plug in any HTTP service that implements the generic ticketer contract
- Local development: Register a local or tunneled reference service for end-to-end testing
- Payload adapters: Use templates when the partner API shape differs from the default contract without writing Mailroom code
Troubleshooting
"Ticketer definition path is required"
Provide the path to your YAML file as an argument to the command.
"No project selected, please select a project first"
Select a project first using weni project use <project_uuid>.
"'config.webhook_secret' is required unless 'config.skip_webhook_hmac' is set"
Add webhook_secret to your config, or set skip_webhook_hmac: "true|yes|1" when HMAC verification is disabled on both sides.
"'config.\<field>' is not a recognized field"
Only fields listed in this guide are accepted. Check spelling of template and route keys.
URL validation errors
Ensure base_url starts with http:// or https://.
Agent replies do not reach the contact
Confirm the partner is calling the URL from metadata.webhook_base_url on open. If you customize open_template, do not drop that field from metadata.
API errors after creation
The CLI calls POST api/v1/ticketers on the Weni CLI backend. If creation fails, confirm the backend endpoint is available and that your account has permission for the selected project.
Next Steps
After creating a ticketer:
- Use the returned UUID in flows or ticket actions that reference a ticketer
- Open a test ticket and confirm the partner receives the open request
- Confirm history delivery (
batchorone_by_one) matches yourhistory_mode - Verify agent replies and close events reach the platform through webhooks
- Monitor ticket operations in the VTEX CX Platform dashboard
For the full HTTP contract your partner service must implement (endpoints, payloads, HMAC, and template context), see the generic ticketer service documentation in your integration repository (generic-ticketer-service.md).