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

# Update supported purchase fulfillment

> Requires both commerce:sales:read and commerce:sales:fulfillment:write; existing credentials/OAuth grants receive no new scopes. Discover list_tickets with includeCommerce=true, inspect get_ticket purchase evidence, select a human owner, start work, then use the fresh Commerce sourceVersion and a new Idempotency-Key for this intent. The Commerce token is separate from ticket revision. Only routine, paid, non-historical purchases without a refund/active financial operation support fulfillment. This does not book with providers or send a customer message. Agent/credential identity is audited directly. Built-in Agent approvals remain required. Refunds, payouts and booking retries remain human actions. Commerce completion synchronizes the exact ticket cycle; generic Resolve/Cancel cannot bypass policy. On a stale token (409), read current evidence before deciding a new command. On an uncertain response, read the purchase/ticket first and retry the identical body with the same key only to reconcile the same intent; never blindly create a new intent. Current tenant and test/live mode are fixed by authorization.



## OpenAPI

````yaml /openapi.json patch /commerce/sales/{saleId}/fulfillment
openapi: 3.0.3
info:
  title: Visito M2M API
  version: 1.0.0
  description: >-
    Tenant-scoped server-to-server API for channels, conversations, commerce,
    custom AI tools, and WhatsApp templates. Send operations are asynchronous
    and return queued acknowledgements. Expansion adds conversation controls,
    knowledge, sales opportunities, delivery status, reporting, and signed
    webhooks.
servers:
  - url: https://platform-api.visitoai.com/m2m/v1
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Channels
  - name: Conversations
  - name: Commerce
  - name: Custom tools
  - name: WhatsApp templates
  - name: Properties
  - name: Knowledge
  - name: Sales CRM
  - name: Delivery
  - name: Reporting
  - name: Webhooks
paths:
  /commerce/sales/{saleId}/fulfillment:
    patch:
      tags:
        - Commerce
        - Tickets
      summary: Update supported purchase fulfillment
      description: >-
        Requires both commerce:sales:read and commerce:sales:fulfillment:write;
        existing credentials/OAuth grants receive no new scopes. Discover
        list_tickets with includeCommerce=true, inspect get_ticket purchase
        evidence, select a human owner, start work, then use the fresh Commerce
        sourceVersion and a new Idempotency-Key for this intent. The Commerce
        token is separate from ticket revision. Only routine, paid,
        non-historical purchases without a refund/active financial operation
        support fulfillment. This does not book with providers or send a
        customer message. Agent/credential identity is audited directly.
        Built-in Agent approvals remain required. Refunds, payouts and booking
        retries remain human actions. Commerce completion synchronizes the exact
        ticket cycle; generic Resolve/Cancel cannot bypass policy. On a stale
        token (409), read current evidence before deciding a new command. On an
        uncertain response, read the purchase/ticket first and retry the
        identical body with the same key only to reconcile the same intent;
        never blindly create a new intent. Current tenant and test/live mode are
        fixed by authorization.
      operationId: update_commerce_sale_fulfillment
      parameters:
        - name: saleId
          in: path
          required: true
          schema:
            type: string
        - name: Idempotency-Key
          in: header
          required: true
          schema:
            type: string
            minLength: 1
            maxLength: 200
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TicketCommerceFulfillmentInput'
      responses:
        '200':
          description: >-
            Durable Commerce command result. Read back the exact ticket and
            purchase after acceptance or uncertainty.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TicketCommerceReview'
        '400':
          description: Invalid request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TicketApiError'
        '401':
          description: Authentication required.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TicketApiError'
        '403':
          description: Required Commerce permission missing.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TicketApiError'
        '404':
          description: Resource unavailable in this workspace.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TicketApiError'
        '409':
          description: State, revision or idempotency conflict.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TicketApiError'
        '502':
          description: >-
            Uncertain Commerce outcome; inspect source state before retrying the
            same intent.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TicketApiError'
        '503':
          description: Capability unavailable.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TicketApiError'
      security:
        - bearerAuth: []
components:
  schemas:
    TicketCommerceFulfillmentInput:
      type: object
      properties:
        sourceVersion:
          type: string
          pattern: ^[a-f0-9]{64}$
        fulfillmentStatus:
          type: string
          enum:
            - fulfilled
            - unfulfilled
      additionalProperties: false
      required:
        - sourceVersion
        - fulfillmentStatus
    TicketCommerceReview:
      type: object
      properties:
        tenantId:
          type: string
        purchaseId:
          type: string
        reason:
          type: string
        factsKey:
          type: string
        sourceVersion:
          type: string
        asOf:
          type: string
        title:
          type: string
        itemName:
          type: string
        currency:
          type: string
        purchaseKind:
          type: string
        paymentStatus:
          type: string
        fulfillmentStatus:
          type: string
        refundStatus:
          type: string
        bookingStatus:
          type: string
        outcome:
          type: string
        sourceReconciledAt:
          type: string
        stripeMode:
          type: string
          enum:
            - test
            - live
        cycle:
          type: integer
          minimum: 0
        revision:
          type: integer
          minimum: 0
        required:
          type: boolean
        amountMinor:
          type: integer
        historical:
          type: boolean
        providerBookingIds:
          type: array
          items:
            type: string
        permittedActions:
          type: array
          items:
            type: string
            enum:
              - fulfill
              - reconcile
        humanActions:
          type: array
          items:
            type: string
            enum:
              - refund
              - retry_reservation
              - payout
        reconciliation:
          $ref: '#/components/schemas/TicketCommerceReconciliation'
        lastCommand:
          $ref: '#/components/schemas/TicketCommerceCommand'
        source:
          type: object
          properties:
            conversationId:
              type: string
            conversationKey:
              type: string
            channel:
              type: string
            propertyId:
              type: string
          additionalProperties: false
        bookingConfirmed:
          type: boolean
          description: >-
            True only for successful provider booking state plus required stored
            provider identifiers; reconciliation alone never sets this.
      additionalProperties: false
      required:
        - tenantId
        - purchaseId
        - reason
        - factsKey
        - sourceVersion
        - asOf
        - title
        - itemName
        - currency
        - purchaseKind
        - paymentStatus
        - fulfillmentStatus
        - refundStatus
        - stripeMode
        - cycle
        - revision
        - required
        - amountMinor
        - historical
        - providerBookingIds
        - permittedActions
        - humanActions
        - source
        - bookingConfirmed
    TicketApiError:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
            details:
              type: object
              additionalProperties: true
          additionalProperties: false
          required:
            - code
            - message
      additionalProperties: false
      required:
        - error
    TicketCommerceReconciliation:
      type: object
      properties:
        outcome:
          type: string
          enum:
            - completed_externally
            - verified_no_action_required
        reference:
          type: string
        note:
          type: string
        actor:
          $ref: '#/components/schemas/TicketCommerceActor'
        at:
          type: string
      additionalProperties: false
      required:
        - outcome
        - reference
        - note
        - actor
        - at
    TicketCommerceCommand:
      type: object
      properties:
        id:
          type: string
        action:
          type: string
          enum:
            - fulfill
            - reconcile
        actor:
          $ref: '#/components/schemas/TicketCommerceActor'
        at:
          type: string
      additionalProperties: false
      required:
        - id
        - action
        - actor
        - at
    TicketCommerceActor:
      type: object
      properties:
        id:
          type: string
        type:
          type: string
          enum:
            - operator
            - agent
        name:
          type: string
      additionalProperties: false
      required:
        - id
        - type
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Visito M2M API key
      description: Server-side tenant-scoped credential created from Build > API Keys.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.