Chapter: API reference

Developers

API reference

All public endpoints of the VentionDesk API. The list is generated from the server’s registered routes; the access rule per endpoint comes from the checks on the route, the tables from the Zod contracts VentionDesk uses to check requests and shape responses. So what is written here is what the server actually does.

URLs start with https://api.ventiondesk.com. Sign-in, scopes, error format and rate limits are explained in API basics. Required fields are marked with *; an endpoint without a table checks its body with a contract that is not published, or has none.

Access reads as follows: “owner” and “owner and staff members” mean a signed-in person in the web interface; with an API key, such endpoints answer with 403. Endpoints with a scope can also be reached by agent keys that carry this scope.

Tasks

GET/v1/tasks

Read tasks, filtered by project, status, assignee or search text.

Access owner, staff members or agent keys with scope tasks:read

Query parameters

FieldTypeNote
projectUUID
projectSlugText
status"hold" | "todo" | "in_progress" | "question" | "review" | "done"
assignee"owner" | "staff" | "claude" | "external"
claimable"true" | "false"
maxAttemptsInteger≥ 1 | ≤ 20 | Default: 3
limitInteger≥ 1 | ≤ 100 | Default: 20
qTextat least 1 characters

Response

FieldTypeNote
tasksList of Object

POST/v1/tasks

Create a task; very similar open tasks are recognised as duplicates.

Access owner, staff members or agent keys with scope tasks:write

Body (JSON)

FieldTypeNote
projectIdUUID
projectSlugText
title *Textat least 25 characters
descriptionMdTextat least 1 characters
area"frontend" | "backend" | "design" | "infra" | "support"
dueDateDate (YYYY-MM-DD)
estimateMinutesInteger> 0
triggerConditionTextat least 1 characters
evidenceTextat least 1 characters

GET/v1/tasks/:id

A task with description, results and attachments.

Access owner, staff members or agent keys with scope tasks:read

Response

FieldTypeNote
taskObject
resultsList of Object
attachmentsList of Object

PATCH/v1/tasks/:id

Change fields of a task.

Access owner, staff members or agent keys with scope tasks:write

Body (JSON)

FieldTypeNote
titleTextat least 1 characters
descriptionMdText or null
status"hold" | "todo" | "in_progress" | "question" | "review" | "done"
assignee"owner" | "staff" | "claude" | "external" or null
area"frontend" | "backend" | "design" | "infra" | "support" or null
dueDateDate (YYYY-MM-DD) or null
estimateMinutesInteger or null> 0
positionTextat least 1 characters
triggerConditionText or null

POST/v1/tasks/:id/claim

Claim a task atomically — two runs never get the same one.

Access owner, staff members or agent keys with scope tasks:write

Body (JSON)

FieldTypeNote
maxAttemptsInteger≥ 1 | ≤ 20 | Default: 3
runIdUUID

POST/v1/tasks/:id/decision

A person’s approval or rejection of a result; a rejection requires a comment.

Access owner and staff members

Body (JSON)

FieldTypeNote
decision *"approved" | "rejected"
commentMdTextat least 1 characters | at most 20000 characters
attachmentIdsList of UUIDDefault: []

Response

FieldTypeNote
taskObject
resultObject

POST/v1/tasks/:id/handoff

Hand a task over to Claude.

Access owner, staff members or agent keys with scope tasks:write

POST/v1/tasks/:id/result

Report the state of a task (arbeitet, kontrolle, frage, master, blockiert, erledigt).

Access owner, staff members or agent keys with scope tasks:write

Body (JSON)

FieldTypeNote
state *"arbeitet" | "kontrolle" | "frage" | "master" | "blockiert" | "erledigt"
summaryMdTextat least 1 characters
detailsMdTextat least 1 characters
prUrlURL
evidenceTextat least 1 characters
runIdUUID

Agent runs

POST/v1/agent/runs

Start a run of an agent.

Access agent keys only, with scope agent:run

Body (JSON)

FieldTypeNote
projectIdUUID
projectSlugText
metaObject (free-form)Default: {}

Response

FieldTypeNote
runObject

POST/v1/agent/runs/:id/finish

Finish an agent run, with a summary or an error status.

Access agent keys only

Body (JSON)

FieldTypeNote
status *"succeeded" | "failed"
summaryTextat least 1 characters

Response

FieldTypeNote
runObject

POST/v1/agent/runs/:id/heartbeat

Liveness signal of a running agent run.

Access agent keys only

Response

FieldTypeNote
runObject

Projects

POST/v1/errors/:id/resolve

Mark an open error as resolved — first at the error tracker (Sentry, Bugsnag, Rollbar) with the access of the error source, and only on success in VentionDesk. If the provider fails (access is read-only, error unknown, no response), the error stays open: 409 or 502 with the reason. For the owner, staff members and agents with errors:write. Hiding and deleting are not available here.

Access owner, staff members or agent keys with scope errors:write

Response

FieldTypeNote
issueObject
changedtrue | false

POST/v1/errors/:id/task

Create a task from an error.

Access owner and staff members

GET/v1/errors/summary

Error counts across all projects for the overview.

Access owner and staff members

Response

FieldTypeNote
projectsList of Object

POST/v1/monitors/probe

Check a monitor URL before creating it and report redirects including the final target.

Access owner and staff members

Body (JSON)

FieldTypeNote
url *URLat most 2048 characters

GET/v1/projects

Projects the account or key may see.

Access owner, staff members or agent keys with scope projects:read

Query parameters

FieldTypeNote
status"active" | "blocked" | "review" | "paused"
includeArchived"true" | "false"
qTextat least 1 characters

Response

FieldTypeNote
projectsList of Object

GET/v1/projects/:id

A project by its ID.

Access owner, staff members or agent keys with scope projects:read

PATCH/v1/projects/:id/customer

Assign a project to another customer; tickets, drafts and documents move along.

Access owner

Body (JSON)

FieldTypeNote
customerId *UUID

Response

FieldTypeNote
projectObject
changedtrue | false
movedObject

GET/v1/projects/:id/deploy

Which deploy targets exist and what each one is missing.

Access owner

Response

FieldTypeNote
targetsList of Object

POST/v1/projects/:id/deploy

Trigger a deploy (202: triggered, not successful).

Access owner

Body (JSON)

FieldTypeNote
target *"production" | "staging" | "preview"
provider"vercel" | "render"

Response

FieldTypeNote
provider"vercel" | "render"
target"production" | "staging" | "preview"
externalIdText or null
startedInteger> 0

POST/v1/projects/:id/error-sources

Assign a project at the error tracker to this project.

Access owner and staff members

Body (JSON)

FieldTypeNote
provider *"sentry" | "bugsnag" | "rollbar"
externalId *Textat least 1 characters | at most 200 characters

DELETE/v1/projects/:id/error-sources/:sourceId

Detach an error source from the project.

Access owner and staff members

GET/v1/projects/:id/errors

Errors from Sentry, Bugsnag or Rollbar for this project. An agent with errors:read gets the errors of its projects, without sources and connections.

Access owner, staff members or agent keys with scope errors:read

Response

FieldTypeNote
issuesList of Object
statsObject
sourcesList of Object
providersList of "sentry" | "bugsnag" | "rollbar"

GET/v1/projects/:id/hosting

The project’s hosting assignments.

Access owner and staff members

Response

FieldTypeNote
mappingsList of Object
providersList of "netlify" | "cloudflare_pages" | "aws_amplify" | "railway" | "flyio" | "digitalocean_app_platform"

POST/v1/projects/:id/hosting

Assign a site, app or service at the hosting provider.

Access owner and staff members

Body (JSON)

FieldTypeNote
provider *"netlify" | "cloudflare_pages" | "aws_amplify" | "railway" | "flyio" | "digitalocean_app_platform"
externalId *Textat least 1 characters | at most 200 characters

DELETE/v1/projects/:id/hosting/:mappingId

Remove a hosting assignment.

Access owner and staff members

DELETE/v1/projects/:id/render-services/:serviceId

Detach an outdated Render service ID from the project.

Access owner

GET/v1/projects/:id/report

The project status for a report: progress, tasks per status, open and overdue tickets, roadmap, monitors, deployments and open pull requests. No money — neither revenue nor budget nor costs.

Access owner, staff members or agent keys with scope stats:read

GET/v1/projects/:id/roadmap

The roadmap phases of a project in planned order.

Access owner, staff members or agent keys with scope roadmap:write

Response

FieldTypeNote
phasesList of Object

POST/v1/projects/:id/roadmap

Create a roadmap phase. Without sort it goes to the end; the next open phase is the milestone in the cockpit.

Access owner, staff members or agent keys with scope roadmap:write

Body (JSON)

FieldTypeNote
title *Textat least 1 characters | at most 200 characters
startsOn *Textfixed pattern
endsOn *Textfixed pattern
sortInteger≥ 0

PATCH/v1/projects/:id/roadmap/:phaseId

Change a phase — title, period, done or order, only the fields sent. The API does not delete.

Access owner, staff members or agent keys with scope roadmap:write

Body (JSON)

FieldTypeNote
titleTextat least 1 characters | at most 200 characters
startsOnTextfixed pattern
endsOnTextfixed pattern
donetrue | false
sortInteger≥ 0

POST/v1/projects/:id/sync

Sync the project’s GitHub data right away instead of overnight.

Access owner and staff members

GET/v1/projects/:id/time

The time entries of a project: day, duration, description, task, billable and billed yes/no, name of the person — without hourly rate, amount and invoice ID.

Access owner, staff members or agent keys with scope time:read

Query parameters

FieldTypeNote
fromTextfixed pattern
toTextfixed pattern
limitInteger≥ 1 | ≤ 500 | Default: 200

Response

FieldTypeNote
entriesList of Object
totalSecondsInteger≥ 0

GET/v1/projects/by-slug/:slug

A project by its slug.

Access owner, staff members or agent keys with scope projects:read

Tickets

GET/v1/tickets

Read tickets, filtered by status, channel, priority, project or customer.

Access owner, staff members or agent keys with scope tickets:read

Query parameters

FieldTypeNote
status"open" | "in_progress" | "waiting" | "resolved"
source"contact_form" | "app" | "email" | "monitor" | "portal" | "phone" | "on_site" | "stripe" | "api"
priority"low" | "normal" | "high" | "critical"
projectUUID
projectSlugText
customerUUID
withSla"true" | "false"
qTextat least 1 characters
limitInteger≥ 1 | ≤ 100 | Default: 50

Response

FieldTypeNote
ticketsList of Object

POST/v1/tickets

Create a ticket, for example after a phone call.

Access owner, staff members or agent keys with scope tickets:write

Body (JSON)

FieldTypeNote
subject *Textat least 3 characters
bodyMd *Textat least 1 characters
source *"contact_form" | "app" | "email" | "monitor" | "portal" | "phone" | "on_site" | "stripe" | "api"
customerIdUUID or null
projectIdUUID or null
priority"low" | "normal" | "high" | "critical"Default: "normal"
requesterNameText
requesterEmailEmail
requesterMetaObject (free-form)

DELETE/v1/tickets/:id

Delete a ticket.

Access owner and staff members

GET/v1/tickets/:id

A ticket including its history.

Access owner, staff members or agent keys with scope tickets:read

Response

FieldTypeNote
ticketObject
messagesList of Object

PATCH/v1/tickets/:id

Change subject, status, priority, channel, customer, project, assignee or portal visibility of a ticket.

Access owner and staff members

Body (JSON)

FieldTypeNote
subjectTextat least 3 characters
status"open" | "in_progress" | "waiting" | "resolved"
priority"low" | "normal" | "high" | "critical"
source"contact_form" | "app" | "email" | "monitor" | "portal" | "phone" | "on_site" | "stripe" | "api"
customerIdUUID or null
projectIdUUID or null
assignedToUUID or null
portalVisibletrue | false

POST/v1/tickets/:id/messages

Write an entry in the history: internal note or draft. No email goes out.

Access owner, staff members or agent keys with scope tickets:write

Body (JSON)

FieldTypeNote
bodyMd *Textat least 1 characters
isInternalNotetrue | falseDefault: false
isDrafttrue | falseDefault: false

POST/v1/tickets/:id/reply

Reply to the customer — the only way an email goes out. Sets the ticket to “waiting”. An agent’s reply always carries the notice that an AI assistant wrote it, and is limited to 20 per hour and key and 3 per ticket and day (429 above that).

Access owner, staff members or agent keys with scope tickets:reply

Body (JSON)

FieldTypeNote
bodyMd *Textat least 1 characters
isInternalNotetrue | falseDefault: false
isDrafttrue | falseDefault: false
draftIdUUID

POST/v1/tickets/:id/to-task

Create a task from a ticket — the subject as title, the whole history as description.

Access owner and staff members

Body (JSON)

FieldTypeNote
projectId *UUID
titleTextat least 10 characters
assignee"owner" | "staff" | "claude" | "external" or null

GET/v1/tickets/attachments/:id/url

Short-lived URL for an attachment of a ticket — an agent only gets it for tickets of its projects.

Access owner, staff members or agent keys with scope tickets:read

Response

FieldTypeNote
urlURL
expiresInSecondsInteger> 0

Notes

POST/v1/notes

Create a note on a project (project ID or slug).

Access owner, staff members or agent keys with scope notes:write

Body (JSON)

FieldTypeNote
projectIdUUID
projectSlugText
bodyMd *Textat least 1 characters
kind"idea" | "decision" | "risk"Default: "idea"

Response

FieldTypeNote
noteObject

POST/v1/notes/:id/to-task

Create a task from a note.

Access owner and staff members

Body (JSON)

FieldTypeNote
titleTextat least 25 characters
assignee"owner" | "staff" | "claude" | "external" or null

Response

FieldTypeNote
okfalse
errorText
code"note_already_converted"
taskObject

Ideas

POST/v1/ideas

Create an idea — always “Open”. An agent only creates: it does not read, change or delete any idea; without a project only with a key for all projects.

Access owner or agent keys with scope ideas:write

Body (JSON)

FieldTypeNote
title *Textat least 1 characters | at most 200 characters
bodyMdTextat most 20000 characters
tagsList of TextDefault: []
potential"low" | "medium" | "high"
priority"low" | "high"
projectIdUUID or null

Response

FieldTypeNote
ideaObject

Time

GET/v1/time/entries

Read time entries.

Access owner and staff members

Query parameters

FieldTypeNote
fromText
toText
projectUUID
userUUID
unbilled"true" | "false"
limitInteger≥ 1 | ≤ 500 | Default: 200

Response

FieldTypeNote
entriesList of Object

POST/v1/time/entries

Add time afterwards.

Access owner and staff members

Body (JSON)

FieldTypeNote
label *Textat least 1 characters
startedAt *Timestamp (ISO 8601)
endedAt *Timestamp (ISO 8601)
secondsInteger> 0
projectIdUUID or null
ticketIdUUID or null
taskIdUUID or null
billabletrue | falseDefault: true

DELETE/v1/time/entries/:id

Delete a time entry.

Access owner and staff members

PATCH/v1/time/entries/:id

Change a time entry.

Access owner and staff members

Body (JSON)

FieldTypeNote
labelTextat least 1 characters
secondsInteger> 0
billabletrue | false
projectIdUUID or null
ticketIdUUID or null

GET/v1/time/timer

The account’s running timer.

Access owner and staff members

Response

FieldTypeNote
timerObject or null

POST/v1/time/timer/start

Start the timer.

Access owner and staff members

Body (JSON)

FieldTypeNote
labelTextDefault: ""
projectIdUUID or null
ticketIdUUID or null
taskIdUUID or null

POST/v1/time/timer/stop

Stop the timer and record the time as an entry.

Access owner and staff members

GET/v1/time/unbilled

Billable hours not yet invoiced, per project, including the amount.

Access owner

Response

FieldTypeNote
projectsList of Object
totalsObject

Customers

DELETE/v1/customers/:id

Delete a customer including files.

Access owner

Response

FieldTypeNote
customerIdUUID
shortNameText
impactObject
filesObject
portalAccountsObject

GET/v1/customers/:id/deletion

Preview of what would be removed along with a customer.

Access owner

Response

FieldTypeNote
customerIdUUID
shortNameText
deletabletrue | false
reasonText or null
blockersObject
impactObject

POST/v1/customers/:id/portal-access

Give a contact person access to the customer portal.

Access owner

Body (JSON)

FieldTypeNote
email *Email
displayNameTextat least 1 characters

Response

FieldTypeNote
accessObject
mailObject

DELETE/v1/customers/:id/portal-access/:userId

Revoke an account’s portal access. A token already issued stays valid until it is renewed.

Access owner

Response

FieldTypeNote
revokedObject

POST/v1/customers/:id/portal-access/:userId/invite

Send the invitation to the customer portal again.

Access owner

Response

FieldTypeNote
mailObject

Documents

GET/v1/documents

Read documents, filtered by customer, project or type.

Access any signed-in account; its role decides what it sees

Query parameters

FieldTypeNote
customerUUID
projectUUID
type"pdf" | "image" | "sheet" | "contract" | "other"
qTextat least 1 characters | at most 120 characters
limitInteger≥ 1 | ≤ 200 | Default: 50

Response

FieldTypeNote
documentsList of Object

PATCH/v1/documents/:id

Change assignment, type, tags or portal visibility of a document.

Access any signed-in account; its role decides what it sees

Body (JSON)

FieldTypeNote
nameTextat least 1 characters | at most 200 characters
type"pdf" | "image" | "sheet" | "contract" | "other"
projectIdUUID or null
sharedWithPortaltrue | false
tagsList of Text

GET/v1/documents/:id/url

Short-lived URL for downloading a document.

Access any signed-in account; its role decides what it sees

Response

FieldTypeNote
urlURL
expiresInSecondsInteger> 0

Finances

GET/v1/finance/export

Annual export for the tax adviser: ZIP with one CSV per table and the stored documents.

Access owner

GET/v1/invoices

Read invoices, filtered by status, customer or “overdue”. An agent only sees drafts of its projects.

Access owner or agent keys with scope invoices:write

Query parameters

FieldTypeNote
status"draft" | "open" | "overdue" | "paid" | "cancelled"
customerUUID
overdue"true" | "false"
limitInteger≥ 1 | ≤ 200 | Default: 50

Response

FieldTypeNote
invoicesList of Object

POST/v1/invoices

Create an invoice draft — still without an invoice number. Without customerId the project’s customer applies; an agent only creates drafts in one of its projects. Finalising, sending and payments stay with the owner.

Access owner or agent keys with scope invoices:write

Body (JSON)

FieldTypeNote
customerIdUUID
projectIdUUID or null
paymentTermsDaysInteger≥ 1 | ≤ 90
vatRateInteger
vatScheme"standard" | "reverse_charge"
serviceFromTextfixed pattern
serviceToTextfixed pattern
serviceDateEqualsInvoiceDatetrue | falseDefault: false
positionsList of ObjectDefault: []

GET/v1/invoices/:id

An invoice with line items, totals and payments.

Access owner or agent keys with scope invoices:write

Response

FieldTypeNote
invoiceObject
positionsList of Object

POST/v1/invoices/:id/cancel

Cancel a finalised invoice; a cancellation document is created.

Access owner

Body (JSON)

FieldTypeNote
reason *Textat least 3 characters | at most 500 characters
serviceRendered *true | false

Response

FieldTypeNote
invoiceObject
releasedEntriesInteger≥ 0
entries"released" | "failed"
correction"stored" | "skipped" | "failed"
taxOfficeConsenttrue | false

GET/v1/invoices/:id/cancellation/pdf

The cancellation document as a PDF.

Access owner

POST/v1/invoices/:id/cancellation/send

Send the cancellation document by email.

Access owner

Response

FieldTypeNote
mail"sent" | "skipped"
reasonTextmay be missing
invoiceObject

POST/v1/invoices/:id/dunning/send

Send the due reminder level.

Access owner

Response

FieldTypeNote
mail"sent" | "skipped"
reasonTextmay be missing
invoiceObject
levelInteger or null≥ 1 | ≤ 4

POST/v1/invoices/:id/finalize

Finalise a draft: assigns the sequential number, locks the invoice and stores the PDF.

Access owner

Body (JSON)

FieldTypeNote
settleObject

Response

FieldTypeNote
invoiceObject
pdf"stored" | "skipped" | "failed"
payment"none" | "booked" | "failed"
paymentErrorTextmay be missing

POST/v1/invoices/:id/payments

Record a payment or repayment.

Access owner

Body (JSON)

FieldTypeNote
amountCents *Integer
paidOnTextfixed pattern
method"transfer" | "stripe" | "cash" | "other"Default: "transfer"
noteTextat most 500 characters

GET/v1/invoices/:id/pdf

The invoice as a PDF — the document stored when it was finalised.

Access owner

POST/v1/invoices/:id/positions

Add a line item to a draft.

Access owner or agent keys with scope invoices:write

Body (JSON)

FieldTypeNote
description *Textat least 1 characters
quantity *Number> 0
unit"hour" | "flat"Default: "hour"
unitPriceCents *Integer≥ 0
sortInteger

DELETE/v1/invoices/:id/positions/:positionId

Remove a line item from a draft.

Access owner or agent keys with scope invoices:write

PATCH/v1/invoices/:id/positions/:positionId

Change a line item of a draft — only the fields sent. A finalised invoice answers with 409.

Access owner or agent keys with scope invoices:write

Body (JSON)

FieldTypeNote
descriptionTextat least 1 characters
quantityNumber> 0
unit"hour" | "flat"Default: "hour"
unitPriceCentsInteger≥ 0
sortInteger

POST/v1/invoices/:id/remind

Send a payment reminder.

Access owner

Response

FieldTypeNote
mail"sent" | "skipped"
reasonTextmay be missing
invoiceObject

POST/v1/invoices/:id/send

Send a finalised invoice by email.

Access owner

Response

FieldTypeNote
mail"sent" | "skipped"
reasonTextmay be missing
invoiceObject

GET/v1/invoices/:id/stripe-refund

Whether and how much of a Stripe payment can be refunded.

Access owner

POST/v1/invoices/:id/stripe-refund

Refund an invoice paid via Stripe through Stripe; it is booked via the webhook.

Access owner

Body (JSON)

FieldTypeNote
amountCentsInteger> 0

POST/v1/invoices/from-unbilled

Turn a project’s open billable hours into an invoice draft — one line item per time entry.

Access owner or agent keys with scope invoices:write

Body (JSON)

FieldTypeNote
projectId *UUID
untilDateText
paymentTermsDaysInteger≥ 1 | ≤ 90
vatRateInteger
vatScheme"standard" | "reverse_charge"

Response

FieldTypeNote
invoiceObject
entriesInteger≥ 0
hoursNumber≥ 0

GET/v1/quotes

Read quotes. An agent only sees drafts of its projects.

Access owner or agent keys with scope quotes:write

Response

FieldTypeNote
quotesList of Object

POST/v1/quotes

Create a quote draft — still without a number. Without customerId the project’s customer applies; an agent only creates drafts in one of its projects and never for a prospect.

Access owner or agent keys with scope quotes:write

Body (JSON)

FieldTypeNote
title *Textat least 3 characters
customerIdUUID or null
prospectNameText
prospectEmailEmail
projectIdUUID or null
validUntilText
vatRateInteger
vatScheme"standard" | "reverse_charge"
positionsList of ObjectDefault: []

DELETE/v1/quotes/:id

Delete a quote draft — it does not have a number yet.

Access owner or agent keys with scope quotes:write

GET/v1/quotes/:id

A quote with its line items.

Access owner or agent keys with scope quotes:write

Response

FieldTypeNote
quoteObject
positionsList of Object

PATCH/v1/quotes/:id

Change title and validity of a draft. A sent quote answers with 409.

Access owner or agent keys with scope quotes:write

Body (JSON)

FieldTypeNote
titleTextat least 3 characters
validUntilText or nullfixed pattern

GET/v1/quotes/:id/pdf

A quote as a PDF.

Access owner

POST/v1/quotes/:id/positions

Add a line item to a quote draft.

Access owner or agent keys with scope quotes:write

Body (JSON)

FieldTypeNote
description *Textat least 1 characters
quantity *Number> 0
unit"hour" | "flat"Default: "hour"
unitPriceCents *Integer≥ 0
sortInteger

DELETE/v1/quotes/:id/positions/:positionId

Remove a line item from a quote draft.

Access owner or agent keys with scope quotes:write

PATCH/v1/quotes/:id/positions/:positionId

Change a line item of a quote draft — only the fields sent.

Access owner or agent keys with scope quotes:write

Body (JSON)

FieldTypeNote
descriptionTextat least 1 characters
quantityNumber> 0
unit"hour" | "flat"Default: "hour"
unitPriceCentsInteger≥ 0
sortInteger

POST/v1/quotes/:id/send

Send a quote by email.

Access owner

Response

FieldTypeNote
mail"sent" | "skipped"
reasonTextmay be missing
quoteObject

Connections

GET/v1/integrations

The workspace’s connected sources, without secrets.

Access owner and staff members

Response

FieldTypeNote
integrationsList of Object
plattformtrue | false
githubInstallierbartrue | false

POST/v1/integrations

Connect a source. The access is checked with the provider before it is stored.

Access owner

Body (JSON)

FieldTypeNote
provider *"vercel" | "render" | "netlify" | "cloudflare_pages" | "aws_amplify" | "railway" | "flyio" | "digitalocean_app_platform" | "postmark" | "mailgun" | "amazon_ses" | "resend" | "sentry" | "bugsnag" | "rollbar" | "stripe"
fields *Object (free-form)

DELETE/v1/integrations/:id

Remove a connection.

Access owner

PATCH/v1/integrations/:id

Edit a connection; an empty secret stays unchanged.

Access owner

Body (JSON)

FieldTypeNote
fields *Object (free-form)

GET/v1/integrations/:id/webhook

The webhook URL of a connection (Stripe, Sentry, Bugsnag, Rollbar) to enter at the provider.

Access owner

Response

FieldTypeNote
urlURL
signierttrue | false
bereittrue | false

GET/v1/integrations/:provider/error-projects

Projects the access can see at the error tracker.

Access owner and staff members

Response

FieldTypeNote
resourcesList of Object

GET/v1/integrations/:provider/resources

Sites, apps or services the hosting access can see at the provider.

Access owner and staff members

Response

FieldTypeNote
resourcesList of Object

GET/v1/integrations/github/callback

Way back from GitHub after the installation; binds the installation to the workspace.

Access signed state and GitHub sign-in

Query parameters

FieldTypeNote
installation_idTextfixed pattern
setup_actionTextat most 20 characters
codeTextat most 200 characters
stateTextat most 2000 characters

POST/v1/integrations/github/install-url

URL for installing the VentionDesk app on GitHub.

Access owner

Response

FieldTypeNote
urlURL

Account, settings and administration

GET/v1/admin/api-keys

The workspace’s API keys, without plain text.

Access owner

Response

FieldTypeNote
keysList of Object

POST/v1/admin/api-keys

Create an agent or intake key. The plain text appears only in this one response.

Access owner

Body (JSON)

FieldTypeNote
name *Textat least 3 characters
kind"agent" | "intake"Default: "agent"
scopes *List of "projects:read" | "tasks:read" | "tasks:write" | "tickets:read" | "tickets:write" | "tickets:reply" | "notes:write" | "deployments:read" | "agent:run" | "intake:write" | "access-log:write" | "invoices:write" | "errors:read" | "errors:write" | "time:read" | "stats:read" | "quotes:write" | "roadmap:write" | "ideas:write"
projectIds *List of UUID or null
expiresAtTimestamp (ISO 8601)

Response

FieldTypeNote
keyObject
plaintextText

DELETE/v1/admin/api-keys/:id

Revoke a key — takes effect immediately.

Access owner

PATCH/v1/admin/api-keys/:id

Change the permissions and projects of a key — the key itself stays the same.

Access owner

Body (JSON)

FieldTypeNote
scopes *List of "projects:read" | "tasks:read" | "tasks:write" | "tickets:read" | "tickets:write" | "tickets:reply" | "notes:write" | "deployments:read" | "agent:run" | "intake:write" | "access-log:write" | "invoices:write" | "errors:read" | "errors:write" | "time:read" | "stats:read" | "quotes:write" | "roadmap:write" | "ideas:write"
projectIds *List of UUID or null

Response

FieldTypeNote
keyObject

DELETE/v1/admin/api-keys/:id/endgueltig

Permanently delete a revoked key.

Access owner

GET/v1/admin/members

The members of the workspace with their role.

Access owner

Response

FieldTypeNote
membersList of Object

PATCH/v1/admin/members/:id

Change a member’s role.

Access owner

Body (JSON)

FieldTypeNote
role *"owner" | "staff"

Response

FieldTypeNote
memberObject
activeHeretrue | false

DELETE/v1/admin/users/:id

Delete a portal account; name and address in the history are pseudonymised first.

Access owner

Response

FieldTypeNote
removedObject
account"kept" | "deleted" | "locked"

POST/v1/admin/users/invite

Invite a staff member by email.

Access owner

Body (JSON)

FieldTypeNote
email *Email
role *"owner" | "staff"
displayNameTextat least 1 characters

Response

FieldTypeNote
userObject
existingAccounttrue | falsemay be missing | Default: false

GET/v1/ki-apps

Connected AI apps: your own in all workspaces, plus all of the workspace for the owner.

Access owner and staff members

Response

FieldTypeNote
appsList of Object
alleImBetriebtrue | false

POST/v1/ki-apps

Store consent for an AI app (workspace, permissions, projects) — before approval at sign-in. Supabase Auth names the app, not the caller.

Access owner and staff members

Body (JSON)

FieldTypeNote
authorizationId *Textat least 1 characters | at most 200 characters
orgId *UUID
scopes *List of "projects:read" | "tasks:read" | "tasks:write" | "tickets:read" | "tickets:write" | "tickets:reply" | "notes:write" | "deployments:read" | "agent:run" | "intake:write" | "access-log:write" | "invoices:write" | "errors:read" | "errors:write" | "time:read" | "stats:read" | "quotes:write" | "roadmap:write" | "ideas:write"
projectIds *List of UUID or null

Response

FieldTypeNote
appObject

DELETE/v1/ki-apps/:id

Disconnect an AI app — takes effect immediately; for your own, the approval at sign-in is withdrawn as well.

Access owner and staff members

GET/v1/ki-apps/rahmen

What the consent page offers: the person’s workspaces, allowed permissions and projects.

Access owner and staff members

Response

FieldTypeNote
betriebeList of Object
betriebUUID
rolle"owner" | "staff"
erlaubtList of "projects:read" | "tasks:read" | "tasks:write" | "tickets:read" | "tickets:write" | "tickets:reply" | "notes:write" | "deployments:read" | "agent:run" | "intake:write" | "access-log:write" | "invoices:write" | "errors:read" | "errors:write" | "time:read" | "stats:read" | "quotes:write" | "roadmap:write" | "ideas:write"
projekteList of Object

GET/v1/ki-apps/vorgabe

Which permissions staff members may give an AI app.

Access owner and staff members

Response

FieldTypeNote
scopesList of "projects:read" | "tasks:read" | "tasks:write" | "tickets:read" | "tickets:write" | "tickets:reply" | "notes:write" | "deployments:read" | "agent:run" | "intake:write" | "access-log:write" | "invoices:write" | "errors:read" | "errors:write" | "time:read" | "stats:read" | "quotes:write" | "roadmap:write" | "ideas:write"
abWerkList of "projects:read" | "tasks:read" | "tasks:write" | "tickets:read" | "tickets:write" | "tickets:reply" | "notes:write" | "deployments:read" | "agent:run" | "intake:write" | "access-log:write" | "invoices:write" | "errors:read" | "errors:write" | "time:read" | "stats:read" | "quotes:write" | "roadmap:write" | "ideas:write"
waehlbarList of "projects:read" | "tasks:read" | "tasks:write" | "tickets:read" | "tickets:write" | "tickets:reply" | "notes:write" | "deployments:read" | "agent:run" | "intake:write" | "access-log:write" | "invoices:write" | "errors:read" | "errors:write" | "time:read" | "stats:read" | "quotes:write" | "roadmap:write" | "ideas:write"

PUT/v1/ki-apps/vorgabe

Change this default.

Access owner

Body (JSON)

FieldTypeNote
scopes *List of "projects:read" | "tasks:read" | "tasks:write" | "tickets:read" | "tickets:write" | "tickets:reply" | "notes:write" | "deployments:read" | "agent:run" | "intake:write" | "access-log:write" | "invoices:write" | "errors:read" | "errors:write" | "time:read" | "stats:read" | "quotes:write" | "roadmap:write" | "ideas:write"

Response

FieldTypeNote
scopesList of "projects:read" | "tasks:read" | "tasks:write" | "tickets:read" | "tickets:write" | "tickets:reply" | "notes:write" | "deployments:read" | "agent:run" | "intake:write" | "access-log:write" | "invoices:write" | "errors:read" | "errors:write" | "time:read" | "stats:read" | "quotes:write" | "roadmap:write" | "ideas:write"
abWerkList of "projects:read" | "tasks:read" | "tasks:write" | "tickets:read" | "tickets:write" | "tickets:reply" | "notes:write" | "deployments:read" | "agent:run" | "intake:write" | "access-log:write" | "invoices:write" | "errors:read" | "errors:write" | "time:read" | "stats:read" | "quotes:write" | "roadmap:write" | "ideas:write"
waehlbarList of "projects:read" | "tasks:read" | "tasks:write" | "tickets:read" | "tickets:write" | "tickets:reply" | "notes:write" | "deployments:read" | "agent:run" | "intake:write" | "access-log:write" | "invoices:write" | "errors:read" | "errors:write" | "time:read" | "stats:read" | "quotes:write" | "roadmap:write" | "ideas:write"

GET/v1/me

Your own account: role, workspace, workspaces to choose from and service addresses.

Access any signed-in account; its role decides what it sees

Response

FieldTypeNote
idUUID
role"owner" | "staff" | "customer" | "agent"
customerIdUUID or null
displayNameTextat least 1 characters
emailEmail
mfaRequiredtrue | false
intakeObject
organizationObject or nullmay be missing | Default: null
membershipsList of Objectmay be missing | Default: []
supportObject or nullmay be missing
locale"de" | "en" | "zh" | "es" | "hi" | "tr" or nullmay be missing

PATCH/v1/me/locale

Save your own interface language in the account.

Access any signed-in account; its role decides what it sees

Body (JSON)

FieldTypeNote
locale *"de" | "en" | "zh" | "es" | "hi" | "tr"

POST/v1/me/organization

Switch the active workspace if the account belongs to several.

Access any signed-in account; its role decides what it sees

Body (JSON)

FieldTypeNote
orgId *UUID

Response

FieldTypeNote
organizationObject
role"owner" | "staff"

GET/v1/settings

Settings of the workspace, including the letterhead for documents.

Access owner

Response

FieldTypeNote
companyObject

PATCH/v1/settings

Change settings and letterhead.

Access owner

Body (JSON)

FieldTypeNote
company *Object

Response

FieldTypeNote
companyObject

GET/v1/settings/agreements

State of consent to the terms and the data processing agreement.

Access owner

POST/v1/settings/agreements

Accept or decline a new version of the terms or the data processing agreement.

Access owner

Body (JSON)

FieldTypeNote
document *"agb" | "avv"
version *Textat least 1 characters | at most 40 characters
decision *"accepted" | "declined"

GET/v1/settings/benachrichtigungen

Email on a new ticket: on or off, recipients, channels and minimum priority.

Access owner

PATCH/v1/settings/benachrichtigungen

Configure the email on a new ticket (owner only).

Access owner

Body (JSON)

FieldTypeNote
aktiv *true | false
wiederoeffnentrue | false
empfaenger *List of Email or null
kanaele *List of "contact_form" | "app" | "email" | "monitor" | "portal" | "phone" | "on_site" | "stripe" | "api" or null
mindestPrioritaet *"low" | "normal" | "high" | "critical"

GET/v1/settings/mail

Sender for emails to customers and state of your own sender domain.

Access owner

PATCH/v1/settings/mail

Change sender name and sender address.

Access owner

Body (JSON)

FieldTypeNote
absenderNameText or nullat most 60 characters
postfachnameTextat most 40 characters

GET/v1/settings/mail-templates

The workspace’s email templates including the default texts.

Access owner

Response

FieldTypeNote
vorlagenList of Object

DELETE/v1/settings/mail-templates/:kind

Reset an email template to the default text.

Access owner

PUT/v1/settings/mail-templates/:kind

Save an email template.

Access owner

Body (JSON)

FieldTypeNote
subject *Textat least 1 characters | at most 200 characters
html *Textat least 1 characters | at most 102400 characters

Response

FieldTypeNote
kind"invoice_send" | "invoice_reminder" | "dunning" | "invoice_cancellation" | "quote_send" | "ticket_reply" | "ticket_receipt" | "ticket_internal" | "ticket_reopened" | "member_invite" | "portal_invite" | "deletion_reminder"
angepassttrue | false
subjectText or null
htmlText or null
aktualisiertAmText or null
bereinigttrue | false

DELETE/v1/settings/mail/domain

Remove your own sender domain.

Access owner

POST/v1/settings/mail/domain

Create your own sender domain; the response lists the DNS records.

Access owner

Body (JSON)

FieldTypeNote
adresse *Textat least 3 characters | at most 254 characters

POST/v1/settings/mail/domain/verify

Have the DNS records of the sender domain checked.

Access owner

VentionDesk subscription

GET/v1/abo

State of the workspace’s VentionDesk subscription: plan, trial, suspension.

Access owner and staff members

Response

FieldTypeNote
betriebText
tarif"solo" | "team" | "enterprise"
abrechnung"jaehrlich" | "monatlich"
status"trial" | "active" | "past_due" | "canceled"
testphaseBisText or null
laufzeitBisText or null
kuendigtZumText or nullmay be missing | Default: null
loeschungAmText or nullmay be missing | Default: null
gesperrttrue | falsemay be missing | Default: false
sperrGrund"beendet" | "testphase" | "zahlungsverzug" | "anbieter" or nullmay be missing | Default: null
sperreAbText or nullmay be missing | Default: null
plaetzeInteger or null
mitgliederInteger
stripeKundetrue | false
stripeAbotrue | falsemay be missing | Default: false
befreittrue | false
stripeBereittrue | false

POST/v1/abo/cancel

Cancel the VentionDesk subscription at the end of the term.

Access owner

Body (JSON)

FieldTypeNote
nonce *Textfixed pattern
grund"too_expensive" | "missing_features" | "switched_service" | "unused" | "too_complex" | "low_quality" | "customer_service" | "other"
kommentarTextat most 500 characters

Response

FieldTypeNote
angenommentrue
ausstehendtrue | falsemay be missing
hinweisTextmay be missing

POST/v1/abo/change

Change the plan or billing interval of the VentionDesk subscription.

Access owner

Body (JSON)

FieldTypeNote
tarif *"solo" | "team" | "enterprise"
abrechnung *"jaehrlich" | "monatlich"
plaetze *Integer≥ 1 | ≤ 10000
nonce *Textfixed pattern

POST/v1/abo/checkout

Take out a VentionDesk subscription (redirects to Stripe Checkout).

Access owner

Body (JSON)

FieldTypeNote
tarif *"solo" | "team" | "enterprise"
abrechnung *"jaehrlich" | "monatlich"

Response

FieldTypeNote
urlURL

GET/v1/abo/export

Data export of the whole workspace as a ZIP (structure: see Data export).

Access owner

POST/v1/abo/preview

Preview of a plan change with the prorated amount.

Access owner

Body (JSON)

FieldTypeNote
tarif *"solo" | "team" | "enterprise"
abrechnung *"jaehrlich" | "monatlich"
plaetze *Integer≥ 1 | ≤ 10000

Response

FieldTypeNote
waehrungText
anteiligCentInteger
rechnungCentInteger
steuerCentInteger
sofortCentInteger
faelligAmText or null
imTesttrue | false

GET/v1/abo/rechnungen

The invoices from VentionDesk to the workspace.

Access owner

Response

FieldTypeNote
rechnungenList of Object

POST/v1/abo/resume

Withdraw a cancellation while the term is still running.

Access owner

Body (JSON)

FieldTypeNote
nonce *Textfixed pattern

Response

FieldTypeNote
angenommentrue
ausstehendtrue | falsemay be missing
hinweisTextmay be missing

GET/v1/abo/verlauf

History of the subscription: sign-up, changes, cancellation.

Access owner

Response

FieldTypeNote
eintraegeList of Object

POST/v1/abo/zahlungsdaten

Change payment details at Stripe (redirects to Stripe).

Access owner

Body (JSON)

FieldTypeNote
nonce *Textfixed pattern

Response

FieldTypeNote
urlURL

GET/v1/abo/zahlungsmittel

The payment method stored for the subscription.

Access owner

Response

FieldTypeNote
zahlungsmittelObject or null

Public intake

POST/f/:publicKey

HTML form on a third-party site: creates a ticket (application/x-www-form-urlencoded).

Access public project key (vd_pub_…) in the URL

Response

FieldTypeNote
oktrue
ticketObject

POST/v1/contact

Contact form of the VentionDesk website (/kontakt, linked from the legal notice).

Access public

Response

FieldTypeNote
oktrue

POST/v1/intake/reports

Report from the browser of a customer app, optionally with a screenshot — using the public project key.

Access public project key in the header x-ventiondesk-key, allowed origin

Response

FieldTypeNote
oktrue
ticketObject

POST/v1/intake/tickets

Submit a ticket server to server, optionally with a screenshot — using an intake key.

Access intake key (vd_intake_…) as Bearer

Response

FieldTypeNote
oktrue
ticketObject

POST/v1/signup

Sign-up of a new workspace including the owner account.

Access public

Response

FieldTypeNote
oktrue
emailEmail
testphaseBisText
checkoutUrlURL or nullmay be missing | Default: null

MCP

GET/.well-known/oauth-protected-resource

Protected resource metadata (RFC 9728): MCP address and authorisation server (Supabase Auth) for signing in an AI app.

Access public

GET/.well-known/oauth-protected-resource/mcp

The same metadata under the path of the resource — for clients that insert it.

Access public

ALL/mcp

Any method other than POST answers with 405 and Allow: POST.

Access public

POST/mcp

MCP server over HTTP (stateless): the tools for Claude, with an agent key or the token of a connected AI app. Without a valid sign-in, 401 with WWW-Authenticate and the way to the metadata.

Access agent key (vd_live_…) or token of a connected AI app as Bearer

Webhooks

POST/webhooks/errors/:provider/:integrationId

Webhook of an error tracker with a signature in the header (Sentry).

Access provider signature

POST/webhooks/errors/:provider/:integrationId/:token

Webhook of an error tracker with the secret in the URL (Bugsnag, Rollbar).

Access secret in the URL

POST/webhooks/stripe/:orgId

Stripe webhook of a workspace’s own Stripe account: books payments and refunds of invoices.

Access signature Stripe-Signature

Operations and payment link

GET/api/health

Liveness signal of the service — answers as long as the process is running.

Access public

GET/api/health/ready

Readiness: reports which services are configured; “degraded” without a database.

Access public

GET/pay/:token

Payment link of an invoice: redirects (303) to the Stripe payment page. The link is in the invoice email and the PDF.

Access token in the URL

GET/pay/:token/abgebrochen

Return page when the payment was cancelled at Stripe.

Access token in the URL

GET/pay/:token/danke

Return page after a successful payment at Stripe.

Access token in the URL

API reference | VentionDesk Docs