Vic.ai Webhook Subscriptions API

Webhook subscriptions control which events your system receives and where they are delivered. Each company may have one V0 subscription or multiple V2 subscriptions. You can subscribe to all events or a specific subset. If you need to update your subscription to receive all events after trimming it down, pass `"events":["all"]` -- when using `all`, it must be set by itself. ## Partner Onboarding Flow Integration partners can programmatically provision new companies and configure webhook delivery using the V2 API: 1. **Create a company** — `POST /v2/companies` with the company's name, country code, and billing timezone. The new company is automatically linked to your OAuth client, inheriting the organization of your primary company (or specify `organization_id` explicitly). 2. **Create webhook subscriptions** — `POST /v2/companies/{company_id}/subscriptions` with your callback URL and the events you want to receive. 3. **Manage subscriptions** — use `GET`, `PUT`, or `DELETE` on `/v2/companies/{company_id}/subscriptions/{id}` as needed.

OpenAPI Specification

vicai-webhook-subscriptions-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  version: v10.40.4
  contact: {}
  title: Vic.ai Accounts Webhook Subscriptions API
  description: "## Introduction\n\nThe Vic.ai API provides a seamless connection between your Enterprise Resource\nPlanning (ERP) system and the Vic.ai product suite.\n\nThe API is designed to offer three main areas of functionality:\n\n- **Syncing master data:** This refers to the data in your ERP that Vic.ai\n  interacts with. You are required to supply and update this data in Vic.ai, and\n  you also have the option to verify the copy of the masterdata in Vic.ai.\n\n- **Syncing training data:** We need historical data to train your AI model. To\n  that end, the API provides endpoints to sync historical invoices into Vic.ai\n  and to confirm their presence.\n\n- **Subscribing to and receiving webhooks:** Webhooks enable users or automated\n  tasks to interact with your ERP through various actions in the Vic.ai product\n  suite, such as posting an invoice, payment or purchase order or requesting\n  synchronization. You will receive a notification via a webhook when these\n  actions occur.\n\n\nFor US-based integrations, please use the following base API URL:\n\n```\nhttps://api.us.vic.ai\n```\n\nFor integrations based in Norway, use the following base API URL:\n\n```\nhttps://api.no.vic.ai\n```\n\nAll paths mentioned in this documentation should use one of these URLs as the\nbase.\n\nExample:\n\n```bash\ncurl https://api.us.vic.ai/v0/healthCheck \\\n    -H \"Content-Type: application/json\" \\\n    -H \"Authorization: Bearer YOUR_ACCESS_TOKEN\"\n```\n\n## Getting Started\n\nTo begin interacting with the Vic.ai API, you will need the following\ncredentials:\n\n* A Vic.ai client ID\n* A Vic.ai client secret.\n\nThese can be provided to you securely by a Vic.ai representative\n[upon request](https://www.vic.ai/book-a-demo).\n\n**Please note:** These credentials are essentially the keys to your ERP\nintegration. If they fall into the wrong hands, unauthorized parties could\nimpersonate you, gain access to sensitive data, and potentially perform\nmalicious actions. Therefore, it's crucial to keep these credentials safe at all\ntimes to protect your application's integrity and your clients' data.\n\n### Limitations\n\nThe Vic.ai API has the following limitations:\n\n**Rate Limiting:** The API is rate-limited to 500 requests per 10-second time\nframe. If you exceed this limit, you will receive a `429 Too Many Requests`\nresponse. The limit is per Oauth client ID. If you continue to receive `429`s,\nplease contact support with a request id from the response headers.\n"
servers:
- url: https://api.no.stage.vic.ai
  description: staging server, NO
- url: https://api.us.vic.ai
  description: production server, US
- url: https://api.no.vic.ai
  description: production server, NO
security:
- BearerAuth: []
tags:
- name: Webhook Subscriptions
  description: "Webhook subscriptions control which events your system receives and where\nthey are delivered. Each company may have one V0 subscription or multiple\nV2 subscriptions.\n\nYou can subscribe to all events or a specific subset. If you need to update\nyour subscription to receive all events after trimming it down, pass\n`\"events\":[\"all\"]` -- when using `all`, it must be set by itself.\n\n## Partner Onboarding Flow\n\nIntegration partners can programmatically provision new companies and\nconfigure webhook delivery using the V2 API:\n\n1. **Create a company** — `POST /v2/companies` with the company's name,\n   country code, and billing timezone. The new company is automatically\n   linked to your OAuth client, inheriting the organization of your\n   primary company (or specify `organization_id` explicitly).\n\n2. **Create webhook subscriptions** — `POST /v2/companies/{company_id}/subscriptions`\n   with your callback URL and the events you want to receive.\n\n3. **Manage subscriptions** — use `GET`, `PUT`, or `DELETE` on\n   `/v2/companies/{company_id}/subscriptions/{id}` as needed.\n"
paths:
  /v0/subscription:
    get:
      description: 'Get the current V0 webhook subscription if one exists.

        '
      summary: Get current V0 webhook subscription
      operationId: getSubscription
      tags:
      - Webhook Subscriptions
      responses:
        '200':
          $ref: '#/components/responses/SubscriptionResponse'
        '429':
          $ref: '#/components/responses/TooManyRequestsResponse'
        4XX:
          $ref: '#/components/responses/ErrorResponse'
    put:
      description: 'This request is used to configure or modify a new V0 subscription to user

        and automated actions.

        You must supply a callback url and set an access token that Vic.ai can

        use to authenticate itself in your system. Notifications of user actions

        will proceed via the documented schema.

        The callback url must be https.

        '
      summary: Create new V0 webhook subscription
      operationId: subscribe
      tags:
      - Webhook Subscriptions
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriptionUpsert'
      responses:
        '201':
          $ref: '#/components/responses/SubscriptionUpsertedResponse'
        '429':
          $ref: '#/components/responses/TooManyRequestsResponse'
        4XX:
          $ref: '#/components/responses/ErrorResponse'
      callbacks:
        events:
          https://mycallbackurl.com/events:
            post:
              summary: An event has occurred in Vic
              description: "This is the end point where all newer `V1` events will be sent\nto. The integration must respond to this callback quickly and if\nnecessary update the Vic system later.\n> **Note**: The callback timeout is 15 seconds. Once the timeout\n> has been reached, the request will be considered a failure and\n> a retry will be attempted.\n* All `2XX` responses will be treated as successful.\n* `401` and `403` responses will be treated as failures and be\n  retried with an exponential backoff. Once the retries have\n  been exhausted, the event is discarded.\n* All other `4XX` responses will be treated as successful. If\n  something is to be rejected, you will need to make the\n  appropriate calls to the Vic API to complete the asynchronous\n  handshake. Example: confirming or rejecting an invoice post.\n* All `5XX` responses will be treated as a failure and will be\n  retried with an exponential backoff. Once the retries have\n  been exhausted, the event is  discarded.\n* All events retried will be reattempted at least 5 times.\nPlease expand the callback section below for more details about\neach event emitted.\n"
              parameters:
              - $ref: '#/components/parameters/SubscriptionToken'
              - $ref: '#/components/parameters/RequestId'
              requestBody:
                required: true
                content:
                  application/json:
                    schema:
                      discriminator:
                        propertyName: event
                      oneOf:
                      - $ref: '#/components/schemas/InvoicePostEvent'
                      - $ref: '#/components/schemas/InvoicePostedEvent'
                      - $ref: '#/components/schemas/InvoiceApprovedEvent'
                      - $ref: '#/components/schemas/InvoiceDeletedEvent'
                      - $ref: '#/components/schemas/InvoiceRestoredEvent'
                      - $ref: '#/components/schemas/PurchaseOrderCreatedEvent'
                      - $ref: '#/components/schemas/PurchaseOrderUpdatedEvent'
                      - $ref: '#/components/schemas/PurchaseOrderDeletedEvent'
                      - $ref: '#/components/schemas/PaymentBatchProcessedEvent'
                      - $ref: '#/components/schemas/PaymentStatusUpdatedEvent'
                      - $ref: '#/components/schemas/CreditStatusUpdatedEvent'
              responses:
                2XX:
                  description: 'Event was received successfully. The body of the response

                    will be ignored.

                    '
                4XX:
                  description: 'Event was received successfully. The body of the response

                    will be ignored.

                    '
                5XX:
                  description: 'Event was not received and a retry will be attempted later.

                    The body of the response will be ignored.

                    '
        vendorNew:
          https://mycallbackurl.com/vendorNew:
            post:
              summary: User has added a new vendor in Vic.
              description: 'This request is sent when a user in Vic.ai adds a new vendor to

                the system.

                Request body contains the vendor object.

                A 201 response indicates that the vendor object has been

                successfully persisted to the ERP, and it must contain the ERP''s

                vendor object id as the externalId parameter.

                Any other response will be considered a failure, the vendor

                object `externalId` will not be specified, and the error message

                you specify will be surfaced to the user.

                A 400 response indicates a data validation error.

                *Note:* This callback will timeout after 15 seconds.

                '
              parameters:
              - $ref: '#/components/parameters/SubscriptionToken'
              - $ref: '#/components/parameters/RequestId'
              requestBody:
                required: true
                content:
                  application/json:
                    schema:
                      $ref: '#/components/schemas/VendorCallback'
              responses:
                '201':
                  description: Successful upsert
                  content:
                    application/json:
                      schema:
                        $ref: '#/components/schemas/VendorConfirm'
                '202':
                  description: Acknowledge receipt
                  content:
                    application/json:
                      schema:
                        enum:
                        - OK
                4XX:
                  description: 'Error when posting vendor.  If this is a generic error,

                    use the `Error` schema; if it''s an error reported by the

                    ERP, use the `VendorError` schema.

                    '
                  content:
                    application/json:
                      schema:
                        oneOf:
                        - $ref: '#/components/schemas/Error'
                        - $ref: '#/components/schemas/VendorError'
                5XX:
                  description: unexpected error
                  content:
                    application/json:
                      schema:
                        $ref: '#/components/schemas/Error'
        invoicePost:
          https://mycallbackurl.com/invoicePost:
            post:
              summary: User has selected to post an invoice to the ERP.
              description: 'This request is sent when a user in Vic.ai posts an invoice

                object to the system.

                Request body contains the invoice object (`invoiceData` part) as

                JSON, and corresponding invoice documents as a pdf file

                (`invoiceDocument` part) as multipart form data.

                The `invoiceDocument` part is optional: for integrations

                configured to retrieve the document over the `documentUrl` link

                in `invoiceData`, the embedded `invoiceDocument` part is omitted.

                Contact Vic.ai support to enable link-only delivery.

                A 201 response indicates that the invoice object has been

                successfully persisted to the ERP, and it must contain the ERP''s

                invoice object id as the `externalId` parameter.

                A 202 response indicates that the receipt of the invoice object

                has been acknowledged; an asynchronous update will occur via

                `invoiceConfirm` and the supplied ''X-Request-Id'' in the request

                header will be provided as the `X-Request-Id` header for any

                associated asynchronous updates.

                Any other response will be considered a failure, the invoice

                object `externalId` will not be specified, and the error message

                you specify will be surfaced to the user.

                A 400 response indicates a data validation error.

                This callback will timeout after 5 seconds; to prevent

                inconsistencies, if the request will take longer than 5 seconds,

                it is appropriate to respond with a 202 response code.

                '
              parameters:
              - $ref: '#/components/parameters/SubscriptionToken'
              - $ref: '#/components/parameters/RequestId'
              requestBody:
                required: true
                content:
                  multipart/form-data:
                    schema:
                      type: object
                      required:
                      - invoiceData
                      properties:
                        invoiceData:
                          $ref: '#/components/schemas/Invoice'
                        invoiceDocument:
                          type: string
                          format: binary
                          description: 'The invoice PDF. Optional — omitted for integrations

                            configured for link-only delivery, where the document

                            is fetched from `documentUrl` in `invoiceData`.

                            '
                    encoding:
                      invoiceData:
                        contentType: application/json
                      invoiceDocument:
                        contentType: application/pdf
              responses:
                '201':
                  description: Successful upsert
                  content:
                    application/json:
                      schema:
                        oneOf:
                        - $ref: '#/components/schemas/InvoiceConfirm'
                '202':
                  description: Deferred post, confirmation asynchronous
                4XX:
                  description: invalid invoice data
                  content:
                    application/json:
                      schema:
                        $ref: '#/components/schemas/Error'
                5XX:
                  description: unexpected error
                  content:
                    application/json:
                      schema:
                        $ref: '#/components/schemas/Error'
        invoiceTransfer:
          https://mycallbackurl.com/invoiceTransfer:
            post:
              summary: User has selected to transfer an invoice to the ERP.
              description: 'This request is sent when a user in Vic.ai selects and invoice

                document and *transfers* it to the ERP.

                Request body contains the invoice object (`invoiceData` part) as

                JSON, and may include the invoice PDF (`invoiceDocument` part) as

                multipart form data.

                For integrations configured for link-only delivery, the

                `invoiceDocument` part is omitted and the document is fetched via

                `documentUrl` in `invoiceData`.

                A 201 response indicates that the invoice document has been

                successfully transferred to the ERP, and it must contain the

                ERP''s invoice document id as the externalId parameter.

                A 202 response indicates that the receipt of the invoice

                transfer has been acknowledged and an asynchronous update will

                occur via `invoiceConfirm` operation and the supplied

                `X-Request-Id` in the request header will be provided as the

                `X-Request-Id` header for any associated asynchronous updates.

                Any other response will be considered a failure, the invoice

                object `externalId` will not be specified, and the error message

                you specify will be surfaced to the user.

                A 400 response indicates a data validation error.

                This callback will timeout after 5 seconds and to prevent

                inconsistencies, if the request will take longer than 5 seconds,

                it is appropriate to respond with a 202 response code.

                '
              parameters:
              - $ref: '#/components/parameters/SubscriptionToken'
              - $ref: '#/components/parameters/RequestId'
              requestBody:
                required: true
                content:
                  multipart/form-data:
                    schema:
                      type: object
                      required:
                      - invoiceData
                      properties:
                        invoiceData:
                          $ref: '#/components/schemas/Invoice'
                        invoiceDocument:
                          type: string
                          format: binary
                          description: 'The invoice PDF. Optional — omitted for integrations

                            configured for link-only delivery, where the document

                            is fetched from `documentUrl` in `invoiceData`.

                            '
                    encoding:
                      invoiceData:
                        contentType: application/json
                      invoiceDocument:
                        contentType: application/pdf
              responses:
                '201':
                  description: Successful upsert
                  content:
                    application/json:
                      schema:
                        enum:
                        - OK
                '202':
                  description: Deferred post, confirmation asynchronous
                4XX:
                  description: Unexpected error
                  content:
                    application/json:
                      schema:
                        $ref: '#/components/schemas/Error'
        syncRequest:
          https://mycallbackurl.com/syncRequest:
            post:
              summary: A request to sync all masterdata.
              description: 'This request is sent when a user in Vic.ai triggers a sync of all

                masterdata.

                In response to this message, you''re expected to post masterdata

                (vendors, GL accounts, dimensions) into Vic.ai using the

                respective routes. You may perform a partial update, determining

                which data to update using queries.

                The body of the `syncRequest` contains the `X-Request-Id` and

                this is a  token that should be returned with all upsert actions

                associated  with this `syncRequest`.

                A 200 response indicates that the request has been acknowledged

                and informs the user that the sync has been successfully triggered.

                '
              parameters:
              - $ref: '#/components/parameters/SubscriptionToken'
              requestBody:
                required: true
                content:
                  application/json:
                    schema:
                      $ref: '#/components/schemas/RequestIdCallback'
              responses:
                '200':
                  description: Request acknowledged
                4XX:
                  description: Request unservicable
                  content:
                    application/json:
                      schema:
                        $ref: '#/components/schemas/Error'
    delete:
      description: 'This request is used to cancel a subscription to user actions. In

        conjunction with a post request, you may use this as a first step to

        update subscription URLs or authorization tokens.

        '
      summary: Delete V0 webhook subscription
      operationId: unsubscribe
      tags:
      - Webhook Subscriptions
      responses:
        '201':
          $ref: '#/components/responses/SubscriptionDeletedResponse'
        '429':
          $ref: '#/components/responses/TooManyRequestsResponse'
        4XX:
          $ref: '#/components/responses/ErrorResponse'
  /v2/companies/{company_id}/subscriptions:
    parameters:
    - $ref: '#/components/parameters/CompanyId'
    get:
      description: 'List your webhook subscriptions.

        '
      summary: List webhook subscriptions
      operationId: listSubscriptions
      tags:
      - Webhook Subscriptions
      x-badges:
      - name: V2
        position: after
        color: blue
      - name: Beta
        position: after
        color: orange
      parameters:
      - $ref: '#/components/parameters/PaginationV2'
      responses:
        '200':
          $ref: '#/components/responses/ListSubscriptionsResponseV2'
        4XX:
          $ref: '#/components/responses/ErrorResponseV2'
    post:
      description: Create a new webhook subscription.
      summary: Create a webhook subscription
      operationId: createSubscription
      tags:
      - Webhook Subscriptions
      x-badges:
      - name: V2
        position: after
        color: blue
      - name: Beta
        position: after
        color: orange
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateSubscriptionV2'
      responses:
        '201':
          $ref: '#/components/responses/CreateSubscriptionResponseV2'
        4XX:
          $ref: '#/components/responses/ErrorResponseV2'
  /v2/companies/{company_id}/subscriptions/{id}:
    parameters:
    - $ref: '#/components/parameters/CompanyId'
    get:
      description: Get details of a specific webhook subscription.
      summary: Get a webhook subscription
      operationId: getSubscriptionById
      tags:
      - Webhook Subscriptions
      x-badges:
      - name: V2
        position: after
        color: blue
      - name: Beta
        position: after
        color: orange
      parameters:
      - name: id
        in: path
        required: true
        description: The subscription ID
        schema:
          type: string
      responses:
        '200':
          $ref: '#/components/responses/GetSubscriptionResponseV2'
        '404':
          $ref: '#/components/responses/ResourceNotFoundResponse'
        4XX:
          $ref: '#/components/responses/ErrorResponseV2'
    put:
      description: Update an existing webhook subscription.
      summary: Update a webhook subscription
      operationId: updateSubscription
      tags:
      - Webhook Subscriptions
      x-badges:
      - name: V2
        position: after
        color: blue
      - name: Beta
        position: after
        color: orange
      parameters:
      - name: id
        in: path
        required: true
        description: The subscription ID
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateSubscriptionV2'
      responses:
        '200':
          $ref: '#/components/responses/UpdateSubscriptionResponseV2'
        '404':
          $ref: '#/components/responses/ResourceNotFoundResponse'
        4XX:
          $ref: '#/components/responses/ErrorResponseV2'
    delete:
      description: Delete a webhook subscription.
      summary: Delete a webhook subscription
      operationId: deleteSubscription
      tags:
      - Webhook Subscriptions
      x-badges:
      - name: V2
        position: after
        color: blue
      - name: Beta
        position: after
        color: orange
      parameters:
      - name: id
        in: path
        required: true
        description: The subscription ID
        schema:
          type: string
      responses:
        '204':
          description: Subscription deleted successfully
        '404':
          $ref: '#/components/responses/ResourceNotFoundResponse'
        4XX:
          $ref: '#/components/responses/ErrorResponseV2'
components:
  schemas:
    PurchaseOrderRequestor:
      type: object
      description: The person or entity who requested the purchase order. Resolved to a user by email first, then by full name. If the name matches more than one user in the company, the request is rejected with `422 Unprocessable Entity` — provide the email to disambiguate.
      properties:
        email:
          oneOf:
          - $ref: '#/components/schemas/Email'
          - type: 'null'
        name:
          oneOf:
          - type: string
            maxLength: 255
          - type: 'null'
    VendorError:
      description: 'Data structure for describing errors when posting a vendor to an

        ERP.  Use a string to describe a single error that applies to

        the entire vendor object, or describes a general error when

        attempting to post, e.g. a connection error.  Use an array of

        strings if multiple errors apply to the entire vendor object.

        If errors apply to specific fields in the ERP, in lieu of a string

        return a FieldError object.

        '
      oneOf:
      - $ref: '#/components/schemas/ErrorString'
      - type: array
        maxItems: 64
        items:
          oneOf:
          - $ref: '#/components/schemas/ErrorString'
          - $ref: '#/components/schemas/FieldError'
    NonNegativeMonetaryValue:
      description: 'The monetary value as a string.

        A float **should not** be used. The api will accept a float and it will be

        transformed into a monetary value, but for best results please use a string

        with the proper decimal precision. **Must be greater than or equal to zero.**

        '
      type: string
      format: decimal
      example: '1.00'
    InvoiceLineItemChild:
      type: object
      description: 'A child line item within a grouped invoice line item. Contains a subset

        of fields from the original line item before merging.

        '
      properties:
        index:
          type: integer
          description: The original index of this line item in the invoice.
        description:
          type: string
          description: The line item description.
        number:
          oneOf:
          - type: string
          - type: 'null'
          description: The item number.
        quantityInvoiced:
          type: string
          format: decimal
          description: The quantity invoiced for this line item.
        unitPrice:
          oneOf:
          - $ref: '#/components/schemas/MonetaryValue'
          - type: 'null'
          description: The unit price.
        amountTax:
          oneOf:
          - $ref: '#/components/schemas/MonetaryValue'
          - type: 'null'
          description: The tax amount.
        amountNet:
          oneOf:
          - $ref: '#/components/schemas/MonetaryValue'
          - type: 'null'
          description: The net amount.
        amountSum:
          oneOf:
          - $ref: '#/components/schemas/MonetaryValue'
          - type: 'null'
          description: The total sum amount.
        amountFreight:
          oneOf:
          - $ref: '#/components/schemas/MonetaryValue'
          - type: 'null'
          description: The freight amount.
        internalId:
          oneOf:
          - $ref: '#/components/schemas/InternalId'
          - type: 'null'
          description: The internal ID of the line item.
        taxCode:
          oneOf:
          - $ref: '#/components/schemas/TaxCode'
          - type: 'null'
          description: 'The tax code for this child line item. Each grouped child retains

            its own tax code, which may differ from the merged parent line item.

            '
        vat:
          oneOf:
          - $ref: '#/components/schemas/LineItemVat'
          - type: 'null'
          description: 'The VAT details for this child line item, retained from the original

            line item before merging.

            '
    InvoiceStatus:
      type: string
      description: Contact the support to enable the APPROVED value.
      enum:
      - NOT_READY
      - IN_APPROVALS
      - APPROVED
      - READY_FOR_POST
      - READY_FOR_TRANSFER
      - POSTED
      - TRANSFERRED
    PaymentInfoTermUnit:
      type: string
      description: The payment term units supported.
      enum:
      - DAYS
    TaxCode:
      type: object
      properties:
        id:
          type: string
          format: uuid
        code:
          type: string
          maxLength: 255
        description:
          type: string
          maxLength: 255
          example: Tax code description
        rate:
          type: string
          format: decimal
          example: '0.25'
    PurchaseOrder:
      type: object
      required:
      - internalId
      - internalUpdatedAt
      - status
      - lineItems
      properties:
        internalId:
          type: string
          maxLength: 255
        externalId:
          oneOf:
          - $ref: '#/components/schemas/ExternalId'
          - type: 'null'
        vendor:
          $ref: '#/components/schemas/Vendor'
        internalUpdatedAt:
          type: string
          format: date-time
        issuedOn:
          type: string
          format: date
        createdOn:
          type: string
          format: date
        poNumber:
          type: string
          maxLength: 255
        deliverOn:
          type: string
          format: date
        amount:
          oneOf:
          - $ref: '#/components/schemas/MonetaryValue'
          - type: 'null'
        currencyId:
          oneOf:
          - $ref: '#/components/schemas/Currency'
          - type: 'null'
        status:
          $ref: '#/components/schemas/PurchaseOrderStatus'
        matchingType:
          $ref: '#/components/schemas/PurchaseOrderMatchingType'
        type:
          $ref: '#/components/schemas/PurchaseOrderType'
        description:
          type: string
          maxLength: 255
        requestor:
          oneOf:
          - $ref: '#/components/schemas/PurchaseOrderRequestor'
          - type: 'null'
        siteOwner:
          oneOf:
          - $ref: '#/components/schemas/PurchaseOrderSiteOwner'
          - type: 'null'
        lineItems:
          type: array
          items:
            $ref: '#/components/schemas/PurchaseOrderLineItem'
        paymentTermId:
          oneOf:
          - type: string
            format: uuid
          - type: 'null'
          description: The id of the `PaymentTerm` a purchase order uses.
    VendorConfirm:
      type: object
      required:
      - externalId
      - externalUpdatedAt
      properties:
        externalId:
          oneOf:
          - $ref: '#/components/schemas/ExternalId'
          - type: 'null'
        externalUpdatedAt:
          type: string
          format: date-time
          description: Does not have UTC normalization.
    ExternalData:
      description: A free form json object that is stored with the record.
      type: object
    InvoiceRestoredEvent:
      type: object
      required:
      - id
      - occurred_at
      - event
      - data
      properties:
        id:
          type: string
          description: The ID of the event. This is idempotent.
          format: uuid
        occurred_at:
          type: string
          description: The date and time the event occurred.
          format: date-time
        event:
          type: string
          enum:
          - invoice_restored
        data:
          type: object
          required:
          - internalId
          properties:
            internalId:
              type: string
              example: '123'
            externalId:
              oneOf:
              - $ref: '#/components/schemas/ExternalId'
              - type: 'null'
    PurchaseOrderScheduleLine:
      type: object
      description: A schedule line associated with a purchase order line item.
      required:
      - internalId
      properties:
        internalId:
          type: string
          format: uuid
          description: The internal ID of the schedule line.
        poScheduleLine

# --- truncated at 32 KB (112 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/vicai/refs/heads/main/openapi/vicai-webhook-subscriptions-api-openapi.yml