> ## Documentation Index
> Fetch the complete documentation index at: https://woku.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Update a ticket destination

> All fields optional. Sending `credentials` rotates the stored secret. Sending `kind` switches the provider; `config`/`credentials` are then validated against the NEW kind.



## OpenAPI

````yaml /openapi-v1.json patch /v1/ticket-destinations/{id}
openapi: 3.0.3
info:
  title: Woku Client API v1
  description: >-
    Public Woku Client API. Switch the version selector at the top to view the
    v0 reference.


    This spec covers:

    - **Wokus** — create wokus, fetch review data, submit text/voice reviews,
    share by email.

    - **Companies** — `GET /companies/me` returns the caller company.

    - **Reports** — company-wide and per-tool NPS reports.

    - **External Trackers** — tag your Wokus with identifiers from third-party
    systems (CRM transaction id, ERP order id, etc.) and look them up later.

    - **Ticket Destinations** — configure the SAC platforms (Zendesk,
    Salesforce, Slack), custom HTTP service or email addresses that receive
    AI-triaged support tickets, and the tracker conditions that route a ticket
    to one.

    - **Action Plan Groups** — define which VoC feedback (tracker conditions)
    drafts an improvement plan and who is responsible.

    - **Action Plans** — read AI-drafted plans and drive their lifecycle
    (approve, send to an external tool or work them in woku's managed kanban).


    ## Authentication


    All endpoints require a Bearer token in the `Authorization` header. Obtain
    your company API key from the Woku dashboard.


    ```

    Authorization: Bearer your_api_key_here

    ```


    ## Base URL


    Production: `https://clientapi.woku.app`


    ## Model (External Trackers)


    - **Tracker definition** (`ExternalTracker`): a per-company catalog entry
    like `{ name: 'trr', system: 'crm interno', description: '...' }`. Defined
    by an admin in the Woku dashboard.

    - **Tracker value** (`WokuExternalTrackerValue`): a string value bound to a
    (Woku, Tracker) pair. Multiple Wokus may share the same value.


    ## Model (routing / group conditions)


    `TicketRoutingCondition` (Ticket Destinations) and
    `ActionPlanGroupCondition` (Action Plan Groups) share the same shape: a
    boolean expression of rows over `ExternalTracker` values, AND binding
    tighter than OR. Each row matches when the feedback carries `trackerId` with
    a value that, for operator `equals`, equals `value`, or, for operator `any`,
    is any value at all (the whole tracker; `value` is then omitted).
    `relationToPrevious` joins a row to the previous one (`AND` same group, `OR`
    starts a new group); the first row omits it.
  version: 1.0.0
  contact:
    name: Woku Support
    url: https://woku.app
    email: team@woku.app
servers:
  - url: https://clientapi.woku.app
    description: Production server
security: []
tags:
  - name: Wokus
    description: >-
      Create wokus, fetch review data, submit text and voice reviews, share
      review links by email.
  - name: Companies
    description: Caller-company endpoint.
  - name: Reports
    description: NPS reports for the caller company and individual NPS tools.
  - name: NPS
    description: >-
      Capture NPS scores (company-level or per NPS tool) and fetch NPS tool
      definitions.
  - name: CSAT
    description: >-
      Capture CSAT (1-5 satisfaction) scores company-level or per CSAT tool,
      fetch tool definitions and responses, and submit text and voice feedback.
  - name: CES
    description: >-
      Capture CES (effort) scores company-level or per CES tool, fetch tool
      definitions and responses, and submit text and voice feedback.
  - name: External Trackers
    description: >-
      Tag Wokus with identifiers from external systems and look them up by name
      + value.
  - name: Quarantines
    description: >-
      Check whether a respondent is currently quarantined before prompting for
      feedback.
  - name: Invitations
    description: >-
      Survey distribution: send NPS surveys, forms and woku review invitations
      by email or WhatsApp.
  - name: Forms
    description: Fetch form definitions and submit responses from your own UI.
  - name: Flows
    description: Render flow journeys (ordered wokus with an optional NPS) in your own app.
  - name: Captures
    description: Mobile SDK capture ingestion
  - name: Ticket Destinations
    description: >-
      Configure where AI-triaged support tickets are delivered (Zendesk,
      Salesforce, Slack, a custom HTTP service, or plain email) and the
      tracker-based routing that picks a destination.
  - name: Action Plan Groups
    description: >-
      Define which VoC feedback (tracker conditions) drafts an action plan and
      who the responsibles are.
  - name: Action Plans
    description: >-
      Read AI-drafted improvement plans and drive their lifecycle: approve, send
      to Jira/monday.com/ClickUp/Notion or work them inside woku's managed
      kanban.
paths:
  /v1/ticket-destinations/{id}:
    patch:
      tags:
        - Ticket Destinations
      summary: Update a ticket destination
      description: >-
        All fields optional. Sending `credentials` rotates the stored secret.
        Sending `kind` switches the provider; `config`/`credentials` are then
        validated against the NEW kind.
      operationId: updateTicketDestination
      parameters:
        - $ref: '#/components/parameters/TicketDestinationIdPath'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateTicketDestinationRequest'
            examples:
              rotateCredentials:
                summary: Rotate a custom destination's bearer token
                value:
                  credentials:
                    authType: bearer
                    token: sk_live_new
              disable:
                summary: Temporarily disable a destination
                value:
                  enabled: false
      responses:
        '200':
          description: Destination updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TicketDestination'
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationError'
        '403':
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ForbiddenError'
        '404':
          description: Destination not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotFoundError'
      security:
        - BearerAuth: []
components:
  parameters:
    TicketDestinationIdPath:
      name: id
      in: path
      required: true
      description: MongoDB ObjectId of the ticket destination.
      schema:
        type: string
        pattern: ^[0-9a-fA-F]{24}$
      example: 507f1f77bcf86cd799439021
  schemas:
    UpdateTicketDestinationRequest:
      type: object
      description: >-
        All fields optional; only the ones present are changed. A `credentials`
        payload rotates the stored secret (re-validated and re-encrypted).
        `kind` can change: config/credentials are then validated against the NEW
        kind.
      properties:
        name:
          type: string
          maxLength: 120
        kind:
          type: string
          enum:
            - zendesk
            - salesforce
            - slack
            - custom
            - email
        config:
          type: object
          additionalProperties: true
          description: >-
            Non-secret, kind-specific config, validated per kind:

            - `zendesk`: `{ connectionId, groupId? }`. `connectionId` is the id
            of the company's Zendesk Integration; `groupId` is the optional
            numeric agent group the ticket lands in.

            - `salesforce`: `{ queueId?, caseOrigin? }`. `queueId` is a Case
            Queue id (`"00G..."`, 15 or 18 chars); `caseOrigin` defaults to
            `"Web"`.

            - `slack`: `{ connectionId, channelId, channelLabel? }`.
            `connectionId` is the id of the company's Slack Integration;
            `channelId` is the Slack channel id (`"C..."`); `channelLabel` is a
            display-only name (e.g. `"#soporte"`).

            - `custom`: `{ url, method, headers? }`. `method` is `POST` or
            `PUT`; `headers` are non-secret extra headers (never
            `Authorization`).

            - `email`: `{ emails }`. Up to 20 recipient addresses; the server
            sends the ticket as a formatted email, no external call.
        credentials:
          type: object
          additionalProperties: true
          description: >-
            Present = credential rotation. Write-only, kind-specific
            credentials. Never returned by the API; see `credentialsHint` on the
            response.

            - `zendesk`, `salesforce`, `slack`: authenticate through the
            company's Integration (connected separately in the dashboard). Send
            `{}`.

            - `custom`: `{ authType, ... }` where `authType` is `none`, `basic`
            (adds `username`, `password`), `bearer` (adds `token`) or
            `api-key-header` (adds `headerName`, `headerValue`).

            - `email`: send `{}`. The server owns the mail transport; there is
            no credential to submit.
        aiContext:
          type: string
          maxLength: 2000
        routingConditions:
          type: array
          maxItems: 20
          items:
            $ref: '#/components/schemas/TicketRoutingCondition'
        template:
          $ref: '#/components/schemas/TicketDestinationTemplate'
        enabled:
          type: boolean
    TicketDestination:
      type: object
      description: >-
        Credentials are never included: `credentialsHint` shows only the masked
        last 4 characters of the stored secret (empty for kinds with no secret
        of their own).
      properties:
        _id:
          type: string
          example: 507f1f77bcf86cd799439021
        companyId:
          type: string
        name:
          type: string
        kind:
          type: string
          enum:
            - zendesk
            - salesforce
            - slack
            - custom
            - email
        config:
          type: object
          additionalProperties: true
        aiContext:
          type: string
        routingConditions:
          type: array
          items:
            $ref: '#/components/schemas/TicketRoutingCondition'
        credentialsHint:
          type: string
          description: >-
            Masked preview of the stored secret (e.g. "••••a1b2"). Empty when
            the kind carries no secret of its own.
          example: ••••a1b2
        template:
          $ref: '#/components/schemas/TicketDestinationTemplate'
        enabled:
          type: boolean
          default: true
        status:
          type: string
          enum:
            - active
            - error
          description: >-
            `error` = the last delivery or connection test failed (see
            `lastError`).
        lastDeliveryAt:
          type: string
          format: date-time
        lastError:
          type: string
          description: >-
            Sanitized failure reason of the last delivery attempt. Never
            contains credentials.
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    ValidationError:
      type: object
      properties:
        statusCode:
          type: integer
          example: 400
        message:
          oneOf:
            - type: string
            - type: array
              items:
                type: string
        error:
          type: string
          example: Bad Request
    ForbiddenError:
      type: object
      properties:
        statusCode:
          type: integer
          example: 403
        message:
          type: string
          example: Authentication required
        error:
          type: string
          example: Forbidden
    NotFoundError:
      type: object
      properties:
        statusCode:
          type: integer
          example: 404
        message:
          type: string
          example: External tracker not found
        error:
          type: string
          example: Not Found
    TicketRoutingCondition:
      type: object
      description: >-
        One routing row: the ticket must carry `trackerId` with a value that
        matches per `operator`. Rows form a boolean expression (AND binds
        tighter than OR) via `relationToPrevious`; a destination is used when
        ANY OR-group of its rows fully matches.
      required:
        - trackerId
      properties:
        relationToPrevious:
          type: string
          enum:
            - AND
            - OR
          description: Joins this row to the previous one. Omitted on the first row.
        trackerId:
          type: string
          description: ExternalTracker id (the company's tracker catalog).
          example: 507f1f77bcf86cd799439011
        operator:
          type: string
          enum:
            - equals
            - any
          default: equals
          description: >-
            `equals` matches the tracker value against `value`. `any` matches
            any value of the tracker (the whole tracker; `value` is omitted).
        value:
          type: string
          maxLength: 200
          description: The value the tracker must equal. Required unless operator is "any".
    TicketDestinationTemplate:
      type: object
      description: >-
        Only meaningful for kind `custom`; named kinds
        (zendesk/salesforce/slack/email) use a fixed preset and reject this
        field.
      required:
        - preset
      properties:
        preset:
          type: string
          example: custom
        body:
          type: string
          maxLength: 10000
          description: >-
            Custom JSON body template with `{{path}}` placeholders resolved
            against the canonical ticket envelope. Omit to send the canonical
            envelope unchanged.
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: >-
        Company API key. Obtain this from your Woku dashboard under Settings >
        API Keys. The same key used for the v0 endpoints.

````