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