Docs / API

Praxis API Overview

The Praxis API allows you to integrate your applications with Praxis. Build custom workflows, sync data with other systems, or create your own client applications.

Base URL

https://web.praxislegal.be/api

Authentication

All API requests require authentication using a Bearer token. Obtain a token by logging in:

POST /api/auth/login
Content-Type: application/json

{
  "email": "your@email.com",
  "password": "<enter-password>"
}

Response:
{
  "token": "<redacted-login-token>",
  "user": { ... },
  "firm": { ... }
}

Include the token in all subsequent requests:

Authorization: Bearer <access-token>

For detailed authentication info, see Authentication.

Response Format

All successful responses follow this format:

{
  "success": true,
  "data": { ... }
}

Error responses:

{
  "error": "Error message here"
}

Available Endpoints

Authentication

POST /api/auth/register Always returns 403 REGISTRATION_DISABLED — use /api/admin/users
POST /api/auth/login Authenticate and get token
GET /api/auth/me Get current user info
POST /api/auth/change-password Change password

MFA & SSO

POST /api/mfa/setup/begin Enable multi-factor authentication
POST /api/mfa/verify Verify MFA token
GET /api/sso/login/{firmSlug} Start single sign-on for a firm (OIDC, not SAML)

Cases

GET /api/cases List all cases
GET /api/cases/{id} Get case by ID
POST /api/cases Create new case
PUT /api/cases/{id} Update case
DELETE /api/cases/{id} Delete case
GET /api/cases/stats Get case statistics

Contacts

GET /api/contacts List all contacts
GET /api/contacts/{id} Get contact by ID
POST /api/contacts Create new contact
PUT /api/contacts/{id} Update contact
DELETE /api/contacts/{id} Delete contact

Time Entries

GET /api/time List time entries
GET /api/time/entry/{id} Get time entry by ID
POST /api/time Create time entry
PUT /api/time/entry/{id} Update time entry
POST /api/time/entry/{id}/bill Mark as billed
DELETE /api/time/entry/{id} Delete time entry
GET /api/time/stats Get time statistics

Expenses

GET /api/expenses List all expenses
POST /api/expenses Create expense
PUT /api/expenses/{id} Update expense
DELETE /api/expenses/{id} Delete expense

Deadlines

GET /api/deadlines List all deadlines
GET /api/deadlines/{id} Get deadline by ID
POST /api/deadlines Create deadline
PUT /api/deadlines/{id} Update deadline
POST /api/deadlines/{id}/complete Mark as completed
DELETE /api/deadlines/{id} Delete deadline
GET /api/deadlines/overdue Get overdue deadlines

Invoices

GET /api/invoices List all invoices
GET /api/invoices/{id} Get invoice by ID
POST /api/invoices Create invoice
PUT /api/invoices/{id} Update invoice
POST /api/invoices/{id}/send Mark as sent
POST /api/invoices/{id}/pay Mark as paid
DELETE /api/invoices/{id} Delete invoice

Documents

GET /api/documents List all documents
POST /api/documents/upload Upload a document
GET /api/documents/{id}/download Download a document
DELETE /api/cases/documents/{docId} Delete a document
POST /api/ocr/extract/{id} Extract text from a stored scanned document (OCR)
POST /api/ocr/upload-and-extract Upload a file and extract its text in one call
GET /api/ocr/status OCR availability for this deployment

OCR requires Azure Document Intelligence. Where it is not configured, both extract endpoints return 503 OCR_NOT_CONFIGURED; there is no fallback on this route. Check GET /api/ocr/status before relying on it: available reports whether extraction can run at all. The localAgent field describes a separate local component used by document content extraction and the AI OCR tool, and it does not serve these endpoints.

Document Maker

GET /api/document-maker/typst/templates List available templates
POST /api/document-maker/typst/compile Render a Typst template to PDF

Calendar

GET /api/calendar List calendar events
POST /api/calendar Create calendar event
POST /api/calendar/sync-outlook Trigger external calendar sync

Tasks

GET /api/tasks List all tasks
POST /api/tasks Create task
PUT /api/tasks/{id} Update task
DELETE /api/tasks/{id} Delete task

Notes

GET /api/notes List all notes
POST /api/notes Create note
PUT /api/notes/{id} Update note
DELETE /api/notes/{id} Delete note

E-mails

GET /api/email-threads List email messages
POST /api/email/send Send an email
POST /api/email/{id}/link Link email to a case

Search

GET /api/search?q={query} Global search across all entities

Reports & Analytics

GET /api/analytics/firm Dashboard summary data
GET /api/analytics/revenue-forecast Revenue report
GET /api/time/utilization Time tracking report

Belgian Integrations

GET /api/document-maker/guided/kbo/{number} KBO/BCE company lookup

Praxis Bot

POST /api/ai/chat Send a message to the Praxis Bot

Client Portal

POST /api/collaboration/portal-invite Invite a client to the portal
GET /api/portal/{token} Get shared items for a client
POST /api/collaboration/share Share documents or cases with a client

Sync & Webhooks

POST /api/sync/trigger Trigger a manual data sync
GET /api/sync/status Get sync status
POST /api/webhooks Register a webhook (registration only — see the note below)
GET /api/webhooks List registered webhooks

Webhooks are registration-only today. These endpoints register and list subscriptions, and the manual test-ping endpoint does deliver, but Praxis does not dispatch domain events yet — no case.created, invoice.paid, deadline.overdue or any other of the 14 declared event types is ever emitted. Do not build an integration that depends on receiving them; poll the relevant resource endpoints until this note is removed.

Administration

GET /api/admin/users List firm users (admin only)
POST /api/admin/users Invite a new user (admin only)
PUT /api/admin/users/{id} Change user role (admin only)
GET /api/admin/activity Security audit log (admin only)
GET /api/admin/firm-settings Get firm settings (admin only)
PUT /api/admin/firm-settings Update firm settings (admin only)

Health

GET /api/health API health check (no auth required)

Data Portability (Import & Export)

GET /api/export/{format} Export data. Formats: harvest-csv, vcard, ical, kleos-zip, octopus-csv, exact-csv, gdpr-zip
POST /api/import/file Import data from uploaded file (CSV, vCard, iCal, ZIP)
GET /api/export/{format} List available export formats and descriptions
POST /api/import/file List supported import formats

Rate Limits

API requests are limited to:

Real-time Updates

Praxis supports real-time updates via SignalR. Connect to receive instant notifications when data changes:

const connection = new signalR.HubConnectionBuilder()
    .withUrl("https://web.praxislegal.be/hubs/sync", {
        accessTokenFactory: () => yourToken
    })
    .build();

connection.on("EntityChanged", (entityType, entityId, action) => {
    console.log(`${entityType} ${entityId} was ${action}`);
});

await connection.start();

SDKs & Libraries

Official SDKs coming soon: