Getting started by App

Each Vision App is its own service. It verifies Vision-issued tokens for its own audience, owns its own data, and has its own conventions while the platform is in preview. This page gives you, for each App, the first call and the differences that will otherwise cost you an afternoon.

At a glance

CRMTo-DoCalendarAccountingDirectory
Origincrm.runonvision.comtodo.runonvision.comcalendar.runonvision.comaccounting.runonvision.comdirectory.runonvision.com
Base path/api/crm/v1/api/todo/v1/calendar/v1/apps/accounting/v1/api/v1
Workspace ref formatlowercase sluglowercase slugCWS- + 12AWS- + 12DWS- + 12
Page size (default / max)25 / 5050 / 10050 / 10025 / 5050 / 100
Idempotencybody idempotencyKeybody idempotencyKeyIdempotency-Key header (required)Idempotency-Key header (required)Idempotency-Key header (optional)
Correlation headerX-Correlation-ID (UUID)X-Correlation-ID (UUID)X-Correlation-ID (UUID)X-Request-ID (UUID)X-Request-ID (UUID)
Machine writesLead intake onlyNo (reads only)Call requests, actor bindingsNo (reads only)Yes, with a workspace grant
OpenAPICRMTo-DoCalendarAccountingDirectory

The workspace reference is taken from your token (app_workspace_ref). You never send a workspace header.

CRM

People, organizations, opportunities, tasks and the intake review queue. Scopes are crm:<area>:read|write, for example crm:people:read. A service or agent client can read only the scopes the workspace has also granted to its machine actor.

List people

curl "https://crm.runonvision.com/api/crm/v1/people?limit=25" \
  --header "authorization: Bearer $CRM_TOKEN" \
  --header "x-correlation-id: $(uuidgen)"
  • Pages: pass cursor from the previous response's nextCursor; null means done.
  • Unknown query parameters are rejected with 400.
  • Errors: flat envelope { schemaVersion: "vision-crm-error.v1", code, message, retryable, correlationId, fieldIssues }.
  • Replaying a command with the same idempotencyKey returns 200 with replayed: true.

To-Do

Tasks and lists. Scopes todo:tasks:read, todo:tasks:write (lists are read with todo:tasks:read). Machine clients can read; commands are made by people through Vision.

List open tasks

curl "https://todo.runonvision.com/api/todo/v1/tasks?limit=50" \
  --header "authorization: Bearer $TODO_TOKEN"
  • Mint the token with resource=<To-Do audience> (the only App-audience token available today).
  • The cursor is tied to the scope and sort that produced it; keep them unchanged while paging.
  • Send x-vision-time-zone: Europe/London (an IANA zone) to get due dates bucketed in that zone.

Calendar

Agenda, events, availability, holds and call requests. Scopes are calendar:<area>:read|write, for example calendar:agenda:read.

Read the agenda

curl "https://calendar.runonvision.com/calendar/v1/agenda?from=2026-11-02T00:00:00Z&to=2026-11-09T00:00:00Z&limit=50" \
  --header "authorization: Bearer $CALENDAR_TOKEN"
  • from and to need explicit offsets; the window is at most 93 days.
  • Every *-commands endpoint requires an Idempotency-Key header.
  • Two reads use POST because they take a body: /conflicts and /availability/slots.
  • Errors carry conflict.intervals when a time clash is the cause.

Accounting

Invoices, counterparties, settings and imports. Scopes are accounting:<area>:read|write, for example accounting:invoices:read. Machine clients are read-only.

List overdue invoices

curl "https://accounting.runonvision.com/apps/accounting/v1/invoices?state=overdue&limit=25" \
  --header "authorization: Bearer $ACCOUNTING_TOKEN" \
  --header "x-request-id: $(uuidgen)"
  • Errors are wrapped: { "error": { schemaVersion: "vision-accounting-error.v1", code, message, requestId, retryable, fieldIssues } }.
  • Commands require an Idempotency-Key header (16 to 160 characters of A-Z a-z 0-9 . _ : -).

Directory

The shared people and companies record that other Apps build on. Scopes directory:people:read|write, directory:companies:read|write. A service client may write the scopes its workspace grant allows.

Create a person

curl https://directory.runonvision.com/api/v1/people \
  --request POST \
  --header "authorization: Bearer $DIRECTORY_TOKEN" \
  --header 'content-type: application/json' \
  --header "idempotency-key: $(uuidgen)" \
  --data '{"displayName":"Ada Lovelace"}'
  • Follow changes without polling every record: GET /api/v1/changes?since=<n> returns items, nextSince and hasMore.
  • A replay with the same Idempotency-Key returns the original status and body exactly; the same key with a different body is 409 idempotency_conflict.
  • Errors are wrapped like Accounting's, with lowercase codes.