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

# Create or update a ticket

> Creates a new ticket or updates an existing one identified by `id` (the external ticket ID from the source system).
The partner is derived from the API key.




## OpenAPI

````yaml openapi.yaml post /ticket/{id}
openapi: 3.1.0
info:
  title: Thalamus Partner API
  description: >
    API for external systems (n8n, Zendesk connectors, etc.) to create and
    manage

    tickets, contacts, organizations, and comments in Thalamus.


    ## Authentication

    All endpoints require a Bearer token in the Authorization header.

    API keys are issued per partner and follow the format
    `nerds_{environment}_{random}`.

    The partner context (partner_uuid) is derived from the API key — no need to
    pass it in the request body.


    ## Conventions

    - All create/update endpoints are idempotent (upsert) — if the `id` already
    exists for the partner, the record is updated.

    - IDs in path parameters and request/response bodies refer to the canonical
    identifiers from the partner's source system (e.g., Zendesk ticket ID).

    - Timestamps use ISO 8601 format.

    - All responses follow `{ success, data?, message?, error? }` shape.

    - POST returns `201` when a new record is created, `200` when an existing
    record is updated.

    - Only provided fields are updated — omitted fields remain unchanged
    (partial update).
  version: 1.3.0
  contact:
    name: Thalamus Engineering
    email: development@nerds.nl
servers:
  - url: https://thalamus.nerds.nl/api/v1/partner
    description: Production
  - url: http://localhost:3001/api/v1/partner
    description: Local development
security:
  - BearerAuth: []
tags:
  - name: Tickets
    description: Create, update, and retrieve tickets
  - name: Comments
    description: Create comments on tickets
  - name: Contacts
    description: Create, update, and retrieve contacts
  - name: Organizations
    description: Create, update, and retrieve organizations
  - name: Tasks
    description: Create task records (callbacks, appointments, etc.)
  - name: References
    description: Manage reference data (statuses, types, groups, categories, agents)
paths:
  /ticket/{id}:
    post:
      tags:
        - Tickets
      summary: Create or update a ticket
      description: >
        Creates a new ticket or updates an existing one identified by `id` (the
        external ticket ID from the source system).

        The partner is derived from the API key.
      operationId: upsertTicket
      parameters:
        - $ref: '#/components/parameters/TicketId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TicketUpsertBody'
      responses:
        '200':
          description: Ticket updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TicketResponse'
        '201':
          description: Ticket created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TicketResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/ServerError'
components:
  parameters:
    TicketId:
      name: id
      in: path
      required: true
      description: Ticket ID from the source system (e.g., Zendesk ticket ID)
      schema:
        type: string
        example: '328099'
  schemas:
    TicketUpsertBody:
      type: object
      description: |
        Fields for creating or updating a ticket. All fields are optional on
        update — only provided fields are changed.
      properties:
        organization_id:
          type: string
          nullable: true
          description: >-
            Organization ID as defined in the source system and synced via `POST
            /organization/{id}`
          example: ORG-5001
        contact_id:
          type: string
          nullable: true
          description: >-
            Contact ID as defined in the source system and synced via `POST
            /contact/{id}`
          example: C-10042
        group_id:
          type: string
          nullable: true
          description: >-
            Group ID as defined in the source system and synced via `POST
            /reference/group`
          example: GRP-100
        agent_id:
          type: string
          nullable: true
          description: >-
            Agent ID as defined in the source system and synced via `POST
            /reference/agent`
          example: AGT-42
        title:
          type: string
          nullable: true
          description: Ticket subject/title
          example: Internet connection issue
        status:
          type: string
          nullable: true
          description: >-
            Status id as defined in the source system and synced via `POST
            /reference/status`
          example: open
        priority:
          type: string
          nullable: true
          description: >-
            Priority id as defined in the source system and synced via `POST
            /reference/priority`
          example: high
        type:
          type: string
          nullable: true
          description: >-
            Type id as defined in the source system and synced via `POST
            /reference/type`
          example: support
        category:
          type: string
          nullable: true
          description: >-
            Category id as defined in the source system and synced via `POST
            /reference/category`
          example: technical
        subcategory:
          type: string
          nullable: true
          description: >-
            Subcategory id as defined in the source system and synced via `POST
            /reference/subcategory`
          example: connectivity
        created_at:
          type: string
          format: date-time
          nullable: true
          description: Original creation timestamp (from source system)
          example: '2026-03-09T10:30:00Z'
        updated_at:
          type: string
          format: date-time
          nullable: true
          description: Last update timestamp (from source system)
          example: '2026-03-09T14:15:00Z'
    TicketResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        data:
          type: object
          properties:
            uuid:
              type: string
              format: uuid
            id:
              type: string
              description: Ticket ID (from source system)
            title:
              type: string
              nullable: true
            status:
              type: string
              nullable: true
            priority:
              type: string
              nullable: true
            type:
              type: string
              nullable: true
            category:
              type: string
              nullable: true
            subcategory:
              type: string
              nullable: true
            organization_id:
              type: string
              nullable: true
            contact_id:
              type: string
              nullable: true
            group_id:
              type: string
              nullable: true
            agent_id:
              type: string
              nullable: true
            created_at:
              type: string
              format: date-time
              nullable: true
            updated_at:
              type: string
              format: date-time
              nullable: true
        message:
          type: string
    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
            details:
              type: array
              nullable: true
              items:
                type: object
                properties:
                  field:
                    type: string
                  message:
                    type: string
  responses:
    BadRequest:
      description: Invalid request body or parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: INVALID_REQUEST
              message: 'Validation failed: body is required'
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: UNAUTHORIZED
              message: Invalid or revoked API key
    ServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: SERVER_ERROR
              message: Internal server error
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: Partner API key (e.g. `nerds_live_a8f3d9k2m5n7p1q4r6t8v0w2x4y6z8`)

````