API & integrations
NovuHub exposes a versioned REST API, signed outbound webhooks, an OpenAPI description, calendar feeds and inbound email hooks. The live reference with every field is at /developers on your host; the machine-readable spec is /api/v1/openapi.json.
Authentication
Create a connection token under Settings → Integrations (workspace owner only). The secret is shown once; NovuHub stores only a hash.
GET /api/v1/tasks
Authorization: Bearer wh_…
Tokens are per workspace. Requests are rate-limited per token (120 per minute by default, NOVUHUB_API_RATE_PER_MIN); over the limit you receive 429 with Retry-After and X-RateLimit-* headers. Errors are JSON: {"error": "<code>", "message": "…"}.
Resources
| Resource | Fields |
|---|---|
tasks | title, project, status, priority, assignees, owners, due, desc, tags |
projects | name, desc, status, owners, team, due, color |
contacts | name, email, phone, company, title, tags, notes |
GET /api/v1/<resource> list (paging: ?limit=&offset=)
GET /api/v1/<resource>/<id> one record
POST /api/v1/<resource> create → 201 with the record
PATCH /api/v1/<resource>/<id> update fields
DELETE /api/v1/<resource>/<id>
Writes go through the same optimistic-concurrency path as the app, so API changes appear live for everyone who has the workspace open.
Webhooks
GET /api/v1/webhooks
POST /api/v1/webhooks {"url": "https://…", "events": "task.created,task.updated"} ("*" = all)
DELETE /api/v1/webhooks/<id>
Events: task.created, task.updated, task.deleted, project.*, contact.* (same three verbs). Deliveries are queued and sent by the background engine as POST with JSON {event, data, workspace_id, ts} and the headers X-NovuHub-Event and X-NovuHub-Signature (HMAC-SHA256 of the body with the subscription secret returned on creation). Failed deliveries are retried with exponential back-off (1, 2, 4, 8 minutes, five attempts). Destination URLs must be public HTTPS/HTTP hosts — private networks, loopback and link-local addresses are refused.
Inbound
POST /api/v1/inbound{"title": …}— create a task from an external system (a form tool, a monitoring alert, an email parser) with the same token.- Email webhook (
POST /api/email/webhook, secured withNOVUHUB_EMAIL_WEBHOOK_TOKEN) receives delivery events from your email provider (bounces, complaints) so addresses are suppressed automatically. - Lead form and booking pages are public, signed URLs generated in the app. The lead form link may carry
?c=<campaign id>andutm_source,utm_medium,utm_campaign: the lead is credited to the campaign. - Marketing push API (same token, write scope):
POST /api/v1/marketing/leadswith{name, email, company, phone, source, medium, campaign, message, consent, extId, kind, openDeal}(one object or a list) — leads are matched by e-mail, a campaign by name, UTM slug or id;POST /api/v1/marketing/costswith[{date, campaign, channel, amount, currency, note}];POST /api/v1/marketing/toucheswith[{email, kind, campaign, source, medium, note, ts}]for a website event or a QR scan at the stand. - Inventory push API (same token, write scope; v1.46.0):
POST /api/v1/inventory/itemswith[{number, name, group, unit, cost, price, ean, supplier, reorderPoint, minQty, maxQty, leadDays, packSize, shelfDays, weight, active}](matched by number, then EAN, then name; existing items are updated);POST /api/v1/inventory/levelswith[{item, location, qty, asOf, cost}]— sets the level, the difference to NovuHub is booked as an adjustment;POST /api/v1/inventory/movementswith[{item, type, qty, location, toLocation, date, cost, ref, lot, expiry, reason, note, extId}]— types receipt, sale, transfer, return_in, return_out, adjust, writeoff, count, opening; a movement with the sameextId, or the same ref + item + date + quantity, is never booked twice. Unknown items are created unless the body carries"createItems": false. Up to 2 000 records per call. Read:GET /api/v1/inventory/items(with onHand and onOrder),GET /api/v1/inventory/movements?from=&to=,GET /api/v1/inventory/pos?status=. - Live connectors are configured under Marketing → Data sources (API key or OAuth). For OAuth the server needs
NOVUHUB_GOOGLE_CLIENT_ID/NOVUHUB_GOOGLE_CLIENT_SECRET(GA4, Search Console, Google Ads — Google Ads alsoNOVUHUB_GOOGLE_ADS_DEVELOPER_TOKEN),NOVUHUB_META_APP_ID/NOVUHUB_META_APP_SECRET(Meta Ads) andNOVUHUB_LINKEDIN_CLIENT_ID/NOVUHUB_LINKEDIN_CLIENT_SECRET(LinkedIn Ads),NOVUHUB_MICROSOFT_CLIENT_ID/NOVUHUB_MICROSOFT_CLIENT_SECRET+NOVUHUB_MICROSOFT_ADS_DEVELOPER_TOKEN(Microsoft Ads) andNOVUHUB_DATEV_CLIENT_ID/NOVUHUB_DATEV_CLIENT_SECRET(DATEV, partner credentials;NOVUHUB_DATEV_SANDBOX=1for the sandbox login); the redirect URI to register is<PUBLIC_BASE_URL>/connectors/oauth/<provider>/callback. CleverReach and Xentral use a key / token typed in the app and need nothing on the server. - Newsletters (v1.45.0): a campaign of type Newsletter / e-mail can be written from a doc and sent through a connected Brevo or Mailchimp account (
POST /api/marketing/campaigns/<id>/newsletter, managers only; a test goes to the sender only). The open and click figures come back with the next sync and are credited to the campaign.
Calendar feed
Calendar → Subscribe gives every person a private ICS URL (/cal/<token>.ics) for Google Calendar, Outlook or Apple Calendar. The token is signed with the server secret; regenerate it from the same dialog.
Claude / MCP connector
The same connection tokens power the NovuHub MCP connector for Claude Desktop (mcp/novuhub_mcp_server.py, endpoints under /api/agent/*). From Claude you can search the workspace; list projects, tasks, documents and people; create tasks, projects (with first tasks), SOP documents and folders, mind maps (project + ideas + tasks + connections), tickets, risks and comments; update tasks (status by label, assignees by name or e-mail) and documents (versioned); and draft invoices and quotes. The workspace owner can additionally run the Decision Intelligence analyses.
Guardrails are enforced on the server: the connector never deletes, never changes settings, never sends e-mail and never moves money; every write is recorded in Activity as "AI agent (connector)". Setup is one line in Settings → Integrations; the Mac keeps the script under ~/mcp/.
Good practice
- Keep tokens in a secrets manager; rotate by generating a new one and deleting the old.
- Use
Idempotency-Keysemantics on your side (retry-safe writes): aPOSTthat fails after the server responded may have succeeded — check by listing. - Verify the webhook signature before trusting a payload.