REST · v1 · 50 webhook events

Build on dVersum.

A curated reference for the endpoints you reach for most — authentication, webhooks, and the core resources for clients, invoices, tasks, time tracking and more. Every example is copy-paste runnable.

Base URLhttps://api.dversum.com/api/v1

Introduction

The dVersum API speaks REST over HTTPS. Requests are JSON, responses are JSON. Timestamps are ISO 8601 in UTC. Monetary amounts are integers in cents. IDs are UUIDv4.

Authentication

Authenticate every request with a personal API token in the Authorization header. Create tokens at Settings → API. Each token is scoped to a user + organization; permissions match the user's.

curl
curl https://api.dversum.com/api/v1/clients \
  -H "Authorization: Bearer dvk_live_…"
Never store tokens in frontend code. Server-side integrations get away with a single token; for multi-tenant setups, rotate regularly.

Conventions

IDs
UUIDv4. Path parameters are always named `{id}` or `{resource_id}`.
Money
Integer cents. `12500` = €125.00 — never floats.
Date / time
ISO 8601 with Z suffix (UTC). Rendered in Europe/Berlin for display.
Locale
Set `Accept-Language: de` or `en` — affects generated email content and ZUGFeRD labels.
Fields
Responses use snake_case. Unknown fields in the request body are ignored.

Errors

Errors are JSON with `error` (short machine token) and `message` (human-readable). HTTP status codes follow REST conventions.

HTTP 422
{
  "error": "validation_failed",
  "message": "client_id is required",
  "field": "client_id"
}
StatusMeaning
400Bad request — JSON parse error or missing required field
401Missing or invalid token
403Token is valid but lacks permission for the resource
404Resource does not exist (or belongs to another organization)
409Conflict — e.g. duplicate slug/email
422Validation failed
429Rate limit exceeded — see Rate limits
5xxServer error — retry or contact support

Pagination

List endpoints accept `?page=` and `?per_page=` (max 100). The response includes `total` so you can compute the total number of pages yourself.

curl
curl "https://api.dversum.com/api/v1/invoices?page=2&per_page=50" \
  -H "Authorization: Bearer $DVERSUM_TOKEN"

Rate limits

Per token: 120 requests/minute. On overage the server responds with 429 and a `Retry-After` header. Responses include `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` for monitoring.

Webhook deliveries are rate-limited separately (1000/min per organization). If your endpoint doesn't respond with 2xx within 5s, we retry with exponential backoff up to 5×.

Webhooks

Webhooks push events to your HTTPS endpoint as they happen in dVersum — paid invoices, new tasks, updated projects. Every delivery is signed and idempotent (`Idempotency-Key` header).

Create a subscription

Create a webhook endpoint at Settings → Webhooks or via the API:

POST/webhooks
curl -X POST https://api.dversum.com/api/v1/webhooks \
  -H "Authorization: Bearer $DVERSUM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/dversum-webhook",
    "events": ["invoice.paid", "quote.signed"],
    "active": true
  }'

The `secret` used to sign future payloads is returned in the POST response — keep it safe.

Verify the signature

Every delivery carries `X-Dversum-Signature: sha256=<hex>`. Compute HMAC-SHA-256 over the raw request body using your `secret`, then compare in constant time.

Node.js
import crypto from 'node:crypto'

const signature = req.headers['x-dversum-signature'].replace('sha256=', '')
const expected = crypto
  .createHmac('sha256', process.env.DVERSUM_WEBHOOK_SECRET)
  .update(req.rawBody)
  .digest('hex')

if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
  return res.status(401).end()
}

Available events

50 events across 11 resources.

Invoices
  • invoice.created
  • invoice.updated
  • invoice.sent
  • invoice.paid
  • invoice.partially_paid
  • invoice.overdue
  • invoice.deleted
Quotes
  • quote.created
  • quote.updated
  • quote.sent
  • quote.signed
  • quote.rejected
  • quote.expired
  • quote.converted
  • quote.deleted
Contracts
  • contract.created
  • contract.signed
  • contract.cancelled
Reminders
  • reminder.sent
Clients
  • client.created
  • client.updated
  • client.deleted
Projects
  • project.created
  • project.updated
  • project.archived
  • project.deleted
Tasks
  • task.created
  • task.updated
  • task.completed
  • task.assigned
  • task.moved
  • task.deleted
  • subtask.created
  • subtask.completed
  • subtask.deleted
  • comment.created
Time
  • time_entry.created
  • time_entry.started
  • time_entry.stopped
  • time_entry.updated
  • time_entry.deleted
Pages
  • page.created
  • page.updated
  • page.deleted
Absences
  • absence.created
  • absence.updated
  • absence.deleted
Bookings
  • booking.created
  • booking.cancelled
  • booking.rescheduled

Clients

Clients are the central business contact — invoices, quotes, projects and contracts all reference a client.

GET/clients

List all clients in the organization.

curl
curl https://api.dversum.com/api/v1/clients \
  -H "Authorization: Bearer $DVERSUM_TOKEN"
Sample response
{
  "clients": [
    {
      "id": "01H8Z…",
      "name": "ATAS Vertriebs GmbH",
      "email": "kontakt@atas.de",
      "color": "#45e59f"
    }
  ],
  "total": 47
}
POST/clients

Create a new client.

curl
curl -X POST https://api.dversum.com/api/v1/clients \
  -H "Authorization: Bearer $DVERSUM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "ATAS Vertriebs GmbH",
    "email": "kontakt@atas.de",
    "vat_id": "DE123456789",
    "country": "DE"
  }'
GET/clients/{id}

Get a single client including linked resources.

curl
curl https://api.dversum.com/api/v1/clients/CLIENT_ID \
  -H "Authorization: Bearer $DVERSUM_TOKEN"
PUT/clients/{id}

Update a client.

curl
curl -X PUT https://api.dversum.com/api/v1/clients/CLIENT_ID \
  -H "Authorization: Bearer $DVERSUM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "email": "neu@atas.de" }'
DELETE/clients/{id}

Delete a client (only if no invoices reference it).

curl
curl -X DELETE https://api.dversum.com/api/v1/clients/CLIENT_ID \
  -H "Authorization: Bearer $DVERSUM_TOKEN"

Projects

Projects contain tasks, time entries, pages and whiteboards. A project can optionally be assigned to a client.

GET/projects

List all projects. Filter with ?archived=false or ?client_id=…

curl
curl "https://api.dversum.com/api/v1/projects?archived=false" \
  -H "Authorization: Bearer $DVERSUM_TOKEN"
POST/projects

Create a new project with default kanban columns.

curl
curl -X POST https://api.dversum.com/api/v1/projects \
  -H "Authorization: Bearer $DVERSUM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Q2 Relaunch",
    "client_id": "CLIENT_ID",
    "color": "#45e59f"
  }'
GET/projects/{id}/tasks

List all tasks in a project including column + assignee data.

curl
curl https://api.dversum.com/api/v1/projects/PROJECT_ID/tasks \
  -H "Authorization: Bearer $DVERSUM_TOKEN"
PATCH/projects/{id}/status

Set the project status (active / on_hold / archived).

curl
curl -X PATCH https://api.dversum.com/api/v1/projects/PROJECT_ID/status \
  -H "Authorization: Bearer $DVERSUM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "status": "archived" }'

Tasks

Tasks belong to a project + a kanban column. They support tags, attachments, subtasks and comments.

POST/tasks

Create a task in the given column.

curl
curl -X POST https://api.dversum.com/api/v1/tasks \
  -H "Authorization: Bearer $DVERSUM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Mockup für Landing Page",
    "project_id": "PROJECT_ID",
    "column_id": "COLUMN_ID",
    "due_date": "2026-06-30",
    "assignee_ids": ["USER_ID"]
  }'
PATCH/tasks/{id}/move

Move a task to another column (or project).

curl
curl -X PATCH https://api.dversum.com/api/v1/tasks/TASK_ID/move \
  -H "Authorization: Bearer $DVERSUM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "column_id": "TARGET_COLUMN_ID", "position": 0 }'
PATCH/tasks/{id}/toggle-done

Toggle a task as done or open.

curl
curl -X PATCH https://api.dversum.com/api/v1/tasks/TASK_ID/toggle-done \
  -H "Authorization: Bearer $DVERSUM_TOKEN"
POST/tasks/{taskId}/comments

Post a comment. Mention `@vero` in the body to have the AI reply inline.

curl
curl -X POST https://api.dversum.com/api/v1/tasks/TASK_ID/comments \
  -H "Authorization: Bearer $DVERSUM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "content": "<p>@vero summarise the thread</p>" }'

Invoices

§14 UStG-compliant invoices with ZUGFeRD XML, dunning workflow, and DATEV export. Amounts in cents (integer).

GET/invoices

List invoices. Filters: ?status=, ?client_id=, ?from=YYYY-MM-DD&to=YYYY-MM-DD.

curl
curl "https://api.dversum.com/api/v1/invoices?status=sent&from=2026-01-01" \
  -H "Authorization: Bearer $DVERSUM_TOKEN"
POST/invoices

Create an invoice as a draft. The invoice number is assigned and GoBD-locked only when sent.

curl
curl -X POST https://api.dversum.com/api/v1/invoices \
  -H "Authorization: Bearer $DVERSUM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "CLIENT_ID",
    "issue_date": "2026-06-05",
    "due_date": "2026-06-19",
    "line_items": [
      { "description": "Beratung", "quantity": 8, "unit_price_cents": 12500, "tax_rate": 19 }
    ]
  }'
POST/invoices/{id}/send

Send the invoice to the client. Locks the document (§14 UStG / GoBD), generates the ZUGFeRD PDF, and fires invoice.sent.

curl
curl -X POST https://api.dversum.com/api/v1/invoices/INVOICE_ID/send \
  -H "Authorization: Bearer $DVERSUM_TOKEN"
GET/invoices/{id}/pdf

Download the invoice as a ZUGFeRD PDF/A-3.

curl
curl https://api.dversum.com/api/v1/invoices/INVOICE_ID/pdf \
  -H "Authorization: Bearer $DVERSUM_TOKEN" \
  -o invoice.pdf
POST/invoices/{id}/payments

Record a payment (full or partial) on the invoice.

curl
curl -X POST https://api.dversum.com/api/v1/invoices/INVOICE_ID/payments \
  -H "Authorization: Bearer $DVERSUM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "amount_cents": 119000, "paid_at": "2026-06-12", "method": "transfer" }'
POST/invoices/{id}/credit-note

Create a credit note (GS-) for the invoice — mirrored amounts, ZUGFeRD DocumentTypeCode 381.

curl
curl -X POST https://api.dversum.com/api/v1/invoices/INVOICE_ID/credit-note \
  -H "Authorization: Bearer $DVERSUM_TOKEN"

Quotes

Quotes with digital signature and one-click conversion to invoice.

POST/quotes

Create a new quote.

curl
curl -X POST https://api.dversum.com/api/v1/quotes \
  -H "Authorization: Bearer $DVERSUM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "CLIENT_ID",
    "valid_until": "2026-07-05",
    "line_items": [
      { "description": "Webdesign", "quantity": 1, "unit_price_cents": 350000, "tax_rate": 19 }
    ]
  }'
POST/quotes/{id}/send

Send the quote by email including a signing link.

curl
curl -X POST https://api.dversum.com/api/v1/quotes/QUOTE_ID/send \
  -H "Authorization: Bearer $DVERSUM_TOKEN"
POST/quotes/{id}/convert-to-invoice

Convert a signed quote to an invoice.

curl
curl -X POST https://api.dversum.com/api/v1/quotes/QUOTE_ID/convert-to-invoice \
  -H "Authorization: Bearer $DVERSUM_TOKEN"

Time entries

Time tracking per task or project. Use the timer or post bulk entries — both produce the same data shape.

POST/time-entries/start

Start a timer for the given task.

curl
curl -X POST https://api.dversum.com/api/v1/time-entries/start \
  -H "Authorization: Bearer $DVERSUM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "task_id": "TASK_ID", "description": "Mockup feedback" }'
POST/time-entries/{id}/stop

Stop the running timer.

curl
curl -X POST https://api.dversum.com/api/v1/time-entries/TIME_ENTRY_ID/stop \
  -H "Authorization: Bearer $DVERSUM_TOKEN"
POST/time-entries

Create a time entry after the fact.

curl
curl -X POST https://api.dversum.com/api/v1/time-entries \
  -H "Authorization: Bearer $DVERSUM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "task_id": "TASK_ID",
    "started_at": "2026-06-04T09:00:00Z",
    "ended_at": "2026-06-04T11:30:00Z",
    "billable": true
  }'

Calendar events

Calendar events with optional Google Meet attach. Created events can sync to Google Calendar automatically.

GET/calendar/events

List events in a window (?from=…&to=… as ISO 8601).

curl
curl "https://api.dversum.com/api/v1/calendar/events?from=2026-06-01T00:00:00Z&to=2026-06-30T23:59:59Z" \
  -H "Authorization: Bearer $DVERSUM_TOKEN"
POST/calendar/events

Create an event. Set attach_meet=true to provision a Google Meet link.

curl
curl -X POST https://api.dversum.com/api/v1/calendar/events \
  -H "Authorization: Bearer $DVERSUM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Kickoff",
    "start_time": "2026-06-12T10:00:00Z",
    "end_time": "2026-06-12T11:00:00Z",
    "attach_meet": true,
    "attendee_emails": ["client@example.com"]
  }'

Pages

Notion-style Tiptap pages with a nested hierarchy. Markdown content is converted to ProseMirror server-side — tables included.

POST/pages

Create a new page with optional markdown content.

curl
curl -X POST https://api.dversum.com/api/v1/pages \
  -H "Authorization: Bearer $DVERSUM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Q2 Analyse",
    "icon": "📊",
    "content": "# Q2 Analyse\n\n| Metrik | Wert |\n|---|---|\n| Revenue | 41.804 € |"
  }'
PUT/pages/{id}/content

Replace the page content with markdown (or ProseMirror JSON).

curl
curl -X PUT https://api.dversum.com/api/v1/pages/PAGE_ID/content \
  -H "Authorization: Bearer $DVERSUM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "content": "## Updated section\n\nNeuer Text" }'
GET/pages/tree

Get the full page tree as a nested list.

curl
curl https://api.dversum.com/api/v1/pages/tree \
  -H "Authorization: Bearer $DVERSUM_TOKEN"

Storage

S3-backed file storage with folder hierarchy and WeTransfer-style share links.

POST/storage/files

Upload a file (multipart/form-data, max 100 MB).

curl
curl -X POST https://api.dversum.com/api/v1/storage/files \
  -H "Authorization: Bearer $DVERSUM_TOKEN" \
  -F "file=@./report.pdf" \
  -F "folder_id=FOLDER_ID"
GET/storage/files/{id}/download

Get a presigned S3 URL (valid 5 min) to download the file.

curl
curl https://api.dversum.com/api/v1/storage/files/FILE_ID/download \
  -H "Authorization: Bearer $DVERSUM_TOKEN"
POST/storage/shares/{fileId}

Create a public share link with optional password and expiry.

curl
curl -X POST https://api.dversum.com/api/v1/storage/shares/FILE_ID \
  -H "Authorization: Bearer $DVERSUM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "password": "geheim", "expires_at": "2026-07-01T00:00:00Z", "max_downloads": 10 }'

Bookings

Cal.com-style public booking page per user. Booking endpoints are unauthenticated and return the available slot pool.

GET/public/booking/{user_slug}/{type_slug}

Get event type metadata (name, duration, description).

curl
curl https://api.dversum.com/api/v1/public/booking/admin/termin-mit-naumche
GET/public/booking/{user_slug}/{type_slug}/slots

Compute available slots in window (?from=…&to=… RFC 3339, max 90 days).

curl
curl "https://api.dversum.com/api/v1/public/booking/admin/termin-mit-naumche/slots?from=2026-06-04T00:00:00Z&to=2026-06-11T00:00:00Z"
POST/public/booking/{user_slug}/{type_slug}/book

Book a slot — sends confirmation mail to guest + host and creates the calendar event.

curl
curl -X POST https://api.dversum.com/api/v1/public/booking/admin/termin-mit-naumche/book \
  -H "Content-Type: application/json" \
  -d '{
    "start": "2026-06-05T09:00:00Z",
    "name": "Max Mustermann",
    "email": "max@example.com",
    "agenda": "Kurzes Intro-Gespräch",
    "timezone": "Europe/Berlin"
  }'

SDKs & integrations

MCP server

Model Context Protocol for Claude Desktop, Cursor and other AI clients. 100+ tools for CRUD across all core resources.

npx -y @dversum/mcp-server
Browser extension

dVersum Companion — universal element picker for Chrome/Edge. Saves web content as tasks.

Chrome Web Store →
Postman collection

Complete collection of every endpoint with predefined variables. Coming soon.

Coming soon
OpenAPI 3.1

Machine-readable spec — generate clients for TypeScript, Python, Go. Coming soon.

Coming soon
n8n

Incoming webhooks from n8n (or any automation platform). Per-webhook permissions are fine-grained.

Setup guide →
Zapier / Make

Works today via the webhook trigger. Native app connector follows.

Coming soon

Support

Missing an endpoint? Response shape off? Tell us — we reply in days, not weeks.