Skip to content

Clients and contacts

The hub every other module attaches to: the client record, the people at that client, the paper trail of what changed, and the address lookup the forms use.

33 endpoints across 4 groups. A permission written module.resource.action:own is scoped: :own covers rows that are yours, :any covers everyone’s, and :any satisfies a check for :own.

EndpointPermission
GET /companiescompanies.company.read
POST /companiescompanies.company.write
GET /companies/{company_id}companies.company.read
PATCH /companies/{company_id}companies.company.write
DELETE /companies/{company_id}companies.company.delete
GET /companies/{company_id}/logocompanies.company.read
POST /companies/{company_id}/logocompanies.company.write
DELETE /companies/{company_id}/logocompanies.company.write
GET /companies/{company_id}/panelscompanies.company.read
GET /companies/{company_id}/summarycompanies.company.read
GET /companies/groupscompanies.group.manage
POST /companies/groupscompanies.group.manage
PATCH /companies/groups/{group_id}companies.group.manage
DELETE /companies/groups/{group_id}companies.group.manage
PUT /companies/groups/{group_id}/companiescompanies.group.manage
PUT /companies/groups/{group_id}/membershipscompanies.group.manage
GET /companies/settingscompanies.settings.manage
PUT /companies/settingscompanies.settings.manage
POST /companies/settings/backfill-client-numberscompanies.settings.manage
Parameters and schemas per endpoint

List Companies

Permission: companies.company.read

Query parameters:

NameTypeMeaning
limitinteger(default 50)
offsetinteger(default 0)
qstring
statusstringLifecycle status; comma-separate for several (‘lead,onboarding,active’). Absent means every status, the archived ones included — the screen picks its own default, this endpoint does not.
minebooleanOnly clients I’m assigned to (primary or not) (default false)
sortstringname | client_number | status | created_at | updated_at, ’-’ desc. Default: name
hoursbooleanInclude the budget roll-up; costs three grouped queries (default false)
countbooleanCompute total; set false for name-only lookups (default true)

Returns: 200 · Page_CompanyRead_

Create Company

Permission: companies.company.write

Request body: CompanyCreate

Returns: 201 · CompanyRead

Get Company

Permission: companies.company.read

Path parameters: company_id

Returns: 200 · CompanyRead

Update Company

Permission: companies.company.write

Path parameters: company_id

Request body: CompanyUpdate

Returns: 200 · CompanyRead

Delete Company

Permission: companies.company.delete

Path parameters: company_id

Returns: 204

Serve Company Logo — The logo bytes — behind the same tenant + horizon check as the company itself, so a portal login only ever sees logos of companies in their horizon (#191/#193).

Permission: companies.company.read

Path parameters: company_id

Returns: 200

Upload Company Logo — Upload or replace the client’s logo. Images only, bounded by the instance caps.

Permission: companies.company.write

Path parameters: company_id

Request body: Body_upload_company_logo_api_v1_companies__company_id__logo_post

Returns: 200 · CompanyRead

Section titled “DELETE /api/v1/companies/{company_id}/logo”

Remove Company Logo

Permission: companies.company.write

Path parameters: company_id

Returns: 200 · CompanyRead

Company Panels — Compose the detail-view panels contributed by every enabled module (the hub).

Permission: companies.company.read

Path parameters: company_id

Returns: 200 · PanelData[]

GET /api/v1/companies/{company_id}/summary

Section titled “GET /api/v1/companies/{company_id}/summary”

Company Summary — The client’s vital signs (#364) — openstaand, uren, open taken, laatste contact, verlenging.

Permission: companies.company.read

Path parameters: company_id

Returns: 200 · SummaryData[]

List Groups

Permission: companies.group.manage

Returns: 200 · GroupRead[]

Create Group

Permission: companies.group.manage

Request body: GroupCreate

Returns: 201 · GroupRead

Update Group

Permission: companies.group.manage

Path parameters: group_id

Request body: GroupUpdate

Returns: 200 · GroupRead

DELETE /api/v1/companies/groups/{group_id}

Section titled “DELETE /api/v1/companies/groups/{group_id}”

Delete Group

Permission: companies.group.manage

Path parameters: group_id

Returns: 204

PUT /api/v1/companies/groups/{group_id}/companies

Section titled “PUT /api/v1/companies/groups/{group_id}/companies”

Set Group Companies

Permission: companies.group.manage

Path parameters: group_id

Request body: GroupCompanies

Returns: 204

PUT /api/v1/companies/groups/{group_id}/memberships

Section titled “PUT /api/v1/companies/groups/{group_id}/memberships”

Set Group Memberships

Permission: companies.group.manage

Path parameters: group_id

Request body: GroupMemberships

Returns: 204

Get Company Settings — How this organisation numbers its clients (klantnummer format + sequence).

Permission: companies.settings.manage

Returns: 200 · CompanyNumberingRead

Update Company Settings

Permission: companies.settings.manage

Request body: CompanyNumberingWrite

Returns: 200 · CompanyNumberingRead

POST /api/v1/companies/settings/backfill-client-numbers

Section titled “POST /api/v1/companies/settings/backfill-client-numbers”

Backfill Client Numbers — Number every client that has no number yet, oldest first.

Permission: companies.settings.manage

Returns: 200 · ClientNumberBackfillResult

EndpointPermission
GET /contactscontacts.contact.read
POST /contactscontacts.contact.write
GET /contacts/{contact_id}contacts.contact.read
PATCH /contacts/{contact_id}contacts.contact.write
DELETE /contacts/{contact_id}contacts.contact.delete
POST /contacts/{contact_id}/linkscontacts.link.write
PATCH /contacts/{contact_id}/links/{company_id}contacts.link.write
DELETE /contacts/{contact_id}/links/{company_id}contacts.link.write
GET /contacts/typescontacts.type.read
POST /contacts/typescontacts.type.manage
PATCH /contacts/types/{type_id}contacts.type.manage
DELETE /contacts/types/{type_id}contacts.type.manage
Parameters and schemas per endpoint

List Contacts

Permission: contacts.contact.read

Query parameters:

NameTypeMeaning
limitinteger(default 50)
offsetinteger(default 0)
company_idstring
contact_type_idstring
qstring
sortstringfirst_name | last_name | email | job_title | company | …, ’-’ desc
countbooleanCompute the total. False for pickers and name-only lookups. (default true)

Returns: 200 · Page_ContactRead_

Create Contact

Permission: contacts.contact.write

Request body: ContactCreate

Returns: 201 · ContactRead

Get Contact

Permission: contacts.contact.read

Path parameters: contact_id

Returns: 200 · ContactRead

Update Contact

Permission: contacts.contact.write

Path parameters: contact_id

Request body: ContactUpdate

Returns: 200 · ContactRead

Delete Contact

Permission: contacts.contact.delete

Path parameters: contact_id

Returns: 204

Link Contact To Company

Permission: contacts.link.write

Path parameters: contact_id

Request body: ContactLinkCreate

Returns: 201 · ContactRead

PATCH /api/v1/contacts/{contact_id}/links/{company_id}

Section titled “PATCH /api/v1/contacts/{contact_id}/links/{company_id}”

Update Contact Company Link

Permission: contacts.link.write

Path parameters: contact_id, company_id

Request body: ContactLinkUpdate

Returns: 200 · ContactRead

DELETE /api/v1/contacts/{contact_id}/links/{company_id}

Section titled “DELETE /api/v1/contacts/{contact_id}/links/{company_id}”

Unlink Contact From Company

Permission: contacts.link.write

Path parameters: contact_id, company_id

Returns: 204

List Contact Types

Permission: contacts.type.read

Query parameters:

NameTypeMeaning
include_inactiveboolean(default false)

Returns: 200 · ContactTypeRead[]

Create Contact Type

Permission: contacts.type.manage

Request body: ContactTypeCreate

Returns: 201 · ContactTypeRead

Update Contact Type

Permission: contacts.type.manage

Path parameters: type_id

Request body: ContactTypeUpdate

Returns: 200 · ContactTypeRead

Delete Contact Type

Permission: contacts.type.manage

Path parameters: type_id

Returns: 204

EndpointPermission
GET /activityactivity.read
Parameters and schemas per endpoint

Entity Activity

Permission: activity.read

Query parameters:

NameTypeMeaning
entity_typestring · required
entity_idstring · required
limitinteger(default 20)

Returns: 200 · app__core__activity__schemas__ActivityItem[]

EndpointPermission
GET /addresslookupaddresslookup.lookup
Parameters and schemas per endpoint

Lookup Address

Permission: addresslookup.lookup

Query parameters:

NameTypeMeaning
postal_codestring · required
house_numberstring · required

Returns: 200 · AddressLookupResponse