Something new is coming up soon from Kanishu — stay tuned.

Developers › API reference

Policy Management

Base address https://policy.kanishu.com/api/v1 · Download the OpenAPI description (for Postman, code generators and the like).

Conventions shared by every endpoint — tokens, headers, lists, safe retries, versions, limits — are in the developer guide; error codes are on Error codes. Each endpoint below names the scope a token needs.

Jump to: API access · Acknowledgements · Controls · People · Policies · Read

API access

POST /api/v1/api-access-requests

Create in api access requests

Request fields (JSON body)

allowed_ipsstring (up to 2000), can be null
api_client_idinteger, can be null
purpose requiredstring (up to 1000)
scopes requiredlist of string
validity_daysinteger: 30, 60, 90, can be null

201 — Created. The record is in `data`; its address in `Location`.

GET /api/v1/api-access-requests/pending

Pending (api access requests pending)

ParameterInTypeAbout
fieldsquerystringOnly these fields of each record, comma-separated (e.g. `id,name`; nested: `owner.name`). `id` always comes back.

200 — OK.

POST /api/v1/api-access-requests/{apiAccessRequest}/approve

Approve (api access requests approve)

ParameterInTypeAbout
apiAccessRequest requiredpathinteger

200 — OK.

POST /api/v1/api-access-requests/{apiAccessRequest}/reject

Reject (api access requests reject)

ParameterInTypeAbout
apiAccessRequest requiredpathinteger

Request fields (JSON body)

reason requiredstring (up to 500)

200 — OK.

GET /api/v1/api-access-requests/{apiAccessRequest}/reveal

Reveal (api access requests reveal)

ParameterInTypeAbout
apiAccessRequest requiredpathinteger
fieldsquerystringOnly these fields of each record, comma-separated (e.g. `id,name`; nested: `owner.name`). `id` always comes back.

200 — OK.

Reply fields (1)
tokenstringThe API token, shown this once. Store it in your secrets manager and send it as Authorization: Bearer <token>.

Need fewer? Add ?fields= with the names you want, e.g. ?fields=token.

Acknowledgements

GET /api/v1/acknowledgements

Status (acknowledgements) · scope acknowledgements:request

ParameterInTypeAbout
email requiredquerystring
policy_ids requiredqueryarray
fieldsquerystringOnly these fields of each record, comma-separated (e.g. `id,name`; nested: `owner.name`). `id` always comes back.

200 — OK.

POST /api/v1/acknowledgements

Create in acknowledgements · scope acknowledgements:request

Request fields (JSON body)

email requiredstring (email) (up to 255)
namestring (up to 255), can be null
policy_ids requiredlist of integer
reasonstring (up to 200), can be null

201 — Created. The record is in `data`; its address in `Location`.

GET /api/v1/acknowledgements/policies

Policies (acknowledgements policies) · scope acknowledgements:request

ParameterInTypeAbout
fieldsquerystringOnly these fields of each record, comma-separated (e.g. `id,name`; nested: `owner.name`). `id` always comes back.

200 — OK.

Reply fields (3) — each record in data
idinteger
titlestring
versionstring

Need fewer? Add ?fields= with the names you want, e.g. ?fields=title,version.

Controls

GET /api/v1/controls/audit-feed

Coverage Feed (controls audit feed) · scope controls:audit-read

ParameterInTypeAbout
fieldsquerystringOnly these fields of each record, comma-separated (e.g. `id,name`; nested: `owner.name`). `id` always comes back.

200 — OK.

Reply fields (14) — each record in data

Also in the answer: meta.

frameworkobject
framework.keystring
framework.namestring
summaryobject
summary.controlsinteger
summary.coveredinteger
summary.gapsinteger
gapslist
gaps[].control_refstring
gaps[].titlestring
coveredlist
covered[].control_refstring
covered[].titlestring
covered[].policieslist of string

Need fewer? Add ?fields= with the names you want, e.g. ?fields=framework,summary.

GET /api/v1/controls/coverage

Which controls of a framework your published policies cover · scope controls:read

ParameterInTypeAbout
framework requiredquerystring: iso27001_2022, soc2_tsc, dpdp_2023, gdprOne of: `iso27001_2022` (ISO/IEC 27001:2022 Annex A), `soc2_tsc` (SOC 2 Trust Services Criteria), `dpdp_2023` (India Digital Personal Data Protection Act, 2023), `gdpr` (EU General Data Protection Regulation).
fieldsquerystringOnly these fields of each record, comma-separated (e.g. `id,name`; nested: `owner.name`). `id` always comes back.

200 — The whole framework in one answer (no paging). Business and Enterprise plans.

Reply fields (8) — in data
frameworkobject
framework.keystring
framework.namestring
summaryobject
summary.controlsinteger
summary.coveredinteger
summary.gapsinteger
controlslist

Need fewer? Add ?fields= with the names you want, e.g. ?fields=framework,summary.

People

GET /api/v1/people

List people · scope people:read

ParameterInTypeAbout
pagequeryintegerPage number, from 1.
per_pagequeryintegerItems a page (default 25, at most 100).
fieldsquerystringOnly these fields of each record, comma-separated (e.g. `id,name`; nested: `owner.name`). `id` always comes back.

200 — A page of results.

Reply fields (24) — each record in data

Also in the answer: meta, links.

idstring (uuid)The person's id in People (a UUID). Use it with /people/{person}.
display_namestringThe name shown everywhere in Kanishu.
preferred_namestring, can be nullWhat they like to be called, if different.
work_emailstringTheir work email address; how they are matched to logins in the products.
employee_numberstring, can be nullYour own employee number for them (e.g. from payroll or HR).
typestringemployee, contractor, external (auditor, consultant…) or other.
statusstringpre_joining (joining soon), active, on_leave, leaving (last working day set) or left.
joining_datestring (date), can be nullTheir first working day.
last_working_datestring (date), can be nullTheir last working day, once they are leaving; their logins are switched off after it.
access_end_datestring (date), can be nullWhen their access to Kanishu products ends, if earlier or later than the last working day (e.g. contractors).
departmentobject, can be nullTheir department or team (id and name), from GET /people-organisation.
department.idstring (uuid)
department.namestring
positionobject, can be nullTheir job position (id and name).
position.idstring (uuid)
position.namestring
locationobject, can be nullTheir office or site (id and name).
location.idstring (uuid)
location.namestring
managerobject, can be nullTheir manager in People (id and display_name).
manager.idstring (uuid)
manager.display_namestring
created_atstring (date and time, ISO 8601)
updated_atstring (date and time, ISO 8601)

Need fewer? Add ?fields= with the names you want, e.g. ?fields=display_name,preferred_name.

POST /api/v1/people

Create in people · scope people:write

Request fields (JSON body)

access_end_datestring (date), can be nullWhen their access to Kanishu products ends, if earlier or later than the last working day (e.g. contractors).
display_name requiredstring (up to 255)The name shown everywhere in Kanishu.
employee_numberstring (up to 50), can be nullYour own employee number for them (e.g. from payroll or HR).
employment_statusstring: pre_joining, active, on_leave, leaving, leftpre_joining (joining soon), active, on_leave, leaving (last working day set) or left.
joining_datestring (date), can be nullTheir first working day.
location_idstring (uuid), can be null
manager_person_idstring (uuid), can be nullThe manager's People id.
org_unit_idstring (uuid), can be nullThe department or team id, from GET /people-organisation.
person_typestring: employee, contractor, external, otheremployee, contractor, external (auditor, consultant…) or other.
position_idstring (uuid), can be null
preferred_namestring (up to 255), can be nullWhat they like to be called, if different.
work_emailstring (email) (up to 255), can be nullTheir work email address; how they are matched to logins in the products.

201 — Created. The record is in `data`; its address in `Location`.

Reply fields (24) — in data
idstring (uuid)The person's id in People (a UUID). Use it with /people/{person}.
display_namestringThe name shown everywhere in Kanishu.
preferred_namestring, can be nullWhat they like to be called, if different.
work_emailstringTheir work email address; how they are matched to logins in the products.
employee_numberstring, can be nullYour own employee number for them (e.g. from payroll or HR).
typestringemployee, contractor, external (auditor, consultant…) or other.
statusstringpre_joining (joining soon), active, on_leave, leaving (last working day set) or left.
joining_datestring (date)Their first working day.
last_working_datestring (date), can be nullTheir last working day, once they are leaving; their logins are switched off after it.
access_end_datestring (date), can be nullWhen their access to Kanishu products ends, if earlier or later than the last working day (e.g. contractors).
departmentobjectTheir department or team (id and name), from GET /people-organisation.
department.idstring (uuid)
department.namestring
positionobjectTheir job position (id and name).
position.idstring (uuid)
position.namestring
locationobjectTheir office or site (id and name).
location.idstring (uuid)
location.namestring
managerobject, can be nullTheir manager in People (id and display_name).
manager.idstring (uuid)
manager.display_namestring
created_atstring (date and time, ISO 8601)
updated_atstring (date and time, ISO 8601)

GET /api/v1/people-organisation

Organisation (people organisation) · scope people:read

ParameterInTypeAbout
fieldsquerystringOnly these fields of each record, comma-separated (e.g. `id,name`; nested: `owner.name`). `id` always comes back.

200 — OK. The record is in `data`, with its version in the `ETag` header.

Reply fields (18) — in data
departmentslist
departments[].idstring (uuid)
departments[].namestring
departments[].typestringWhat kind of unit it is (e.g. department, team, business unit).
departments[].codestring
departments[].part_of_idinteger or string, can be nullThe unit this one sits under, or null at the top.
departments[].in_usebooleanfalse when the unit is archived and no longer offered.
positionslist
positions[].idstring (uuid)
positions[].namestring
positions[].codestring, can be null
positions[].in_usebooleanfalse when the position is archived.
locationslist
locations[].idstring (uuid)
locations[].namestring
locations[].codestring, can be null
locations[].citystring, can be null
locations[].in_usebooleanfalse when the location is archived.

Need fewer? Add ?fields= with the names you want, e.g. ?fields=departments,positions.

POST /api/v1/people/joiners

Add a joiner (from their start date) · scope people:write

Request fields (JSON body)

accesslist of string, can be nullLogins they should get, as product key => role (e.g. {"itsm": "agent"}); each one waits for an approval.
access_end_datestring (date), can be nullWhen their access to Kanishu products ends, if earlier or later than the last working day (e.g. contractors).
display_name requiredstring (up to 255)The name shown everywhere in Kanishu.
employee_numberstring (up to 50), can be nullYour own employee number for them (e.g. from payroll or HR).
employment_statusstring: pre_joining, active, on_leave, leaving, leftpre_joining (joining soon), active, on_leave, leaving (last working day set) or left.
joining_datestring (date), can be nullTheir first working day.
location_idstring (uuid), can be null
manager_person_idstring (uuid), can be nullThe manager's People id.
org_unit_idstring (uuid), can be nullThe department or team id, from GET /people-organisation.
person_typestring: employee, contractor, external, otheremployee, contractor, external (auditor, consultant…) or other.
position_idstring (uuid), can be null
preferred_namestring (up to 255), can be nullWhat they like to be called, if different.
start_date requiredstring (date)Their first working day; their logins are prepared for it.
work_emailstring (email) (up to 255), can be nullTheir work email address; how they are matched to logins in the products.

201 — The new person, as GET /people/{person} returns them.

Reply fields (24) — in data
idstring (uuid)The person's id in People (a UUID). Use it with /people/{person}.
display_namestringThe name shown everywhere in Kanishu.
preferred_namestring, can be nullWhat they like to be called, if different.
work_emailstringTheir work email address; how they are matched to logins in the products.
employee_numberstring, can be nullYour own employee number for them (e.g. from payroll or HR).
typestringemployee, contractor, external (auditor, consultant…) or other.
statusstringpre_joining (joining soon), active, on_leave, leaving (last working day set) or left.
joining_datestring (date)Their first working day.
last_working_datestring (date), can be nullTheir last working day, once they are leaving; their logins are switched off after it.
access_end_datestring (date), can be nullWhen their access to Kanishu products ends, if earlier or later than the last working day (e.g. contractors).
departmentobjectTheir department or team (id and name), from GET /people-organisation.
department.idstring (uuid)
department.namestring
positionobjectTheir job position (id and name).
position.idstring (uuid)
position.namestring
locationobjectTheir office or site (id and name).
location.idstring (uuid)
location.namestring
managerobject, can be nullTheir manager in People (id and display_name).
manager.idstring (uuid)
manager.display_namestring
created_atstring (date and time, ISO 8601)
updated_atstring (date and time, ISO 8601)

GET /api/v1/people/{person}

Get one of people · scope people:read

ParameterInTypeAbout
person requiredpathinteger
fieldsquerystringOnly these fields of each record, comma-separated (e.g. `id,name`; nested: `owner.name`). `id` always comes back.

200 — OK. The record is in `data`, with its version in the `ETag` header.

Reply fields (24) — in data
idstring (uuid)The person's id in People (a UUID). Use it with /people/{person}.
display_namestringThe name shown everywhere in Kanishu.
preferred_namestring, can be nullWhat they like to be called, if different.
work_emailstringTheir work email address; how they are matched to logins in the products.
employee_numberstring, can be nullYour own employee number for them (e.g. from payroll or HR).
typestringemployee, contractor, external (auditor, consultant…) or other.
statusstringpre_joining (joining soon), active, on_leave, leaving (last working day set) or left.
joining_datestring (date)Their first working day.
last_working_datestring (date), can be nullTheir last working day, once they are leaving; their logins are switched off after it.
access_end_datestring (date), can be nullWhen their access to Kanishu products ends, if earlier or later than the last working day (e.g. contractors).
departmentobjectTheir department or team (id and name), from GET /people-organisation.
department.idstring (uuid)
department.namestring
positionobjectTheir job position (id and name).
position.idstring (uuid)
position.namestring
locationobjectTheir office or site (id and name).
location.idstring (uuid)
location.namestring
managerobject, can be nullTheir manager in People (id and display_name).
manager.idstring (uuid)
manager.display_namestring
created_atstring (date and time, ISO 8601)
updated_atstring (date and time, ISO 8601)

Need fewer? Add ?fields= with the names you want, e.g. ?fields=display_name,preferred_name.

PATCH /api/v1/people/{person}

Change one of people · scope people:write

ParameterInTypeAbout
person requiredpathinteger

Request fields (JSON body) — send only the fields you change

access_end_datestring (date), can be nullWhen their access to Kanishu products ends, if earlier or later than the last working day (e.g. contractors).
display_namestring (up to 255)The name shown everywhere in Kanishu.
employee_numberstring (up to 50), can be nullYour own employee number for them (e.g. from payroll or HR).
employment_statusstring: pre_joining, active, on_leave, leaving, leftpre_joining (joining soon), active, on_leave, leaving (last working day set) or left.
joining_datestring (date), can be nullTheir first working day.
location_idstring (uuid), can be null
manager_person_idstring (uuid), can be nullThe manager's People id.
org_unit_idstring (uuid), can be nullThe department or team id, from GET /people-organisation.
person_typestring: employee, contractor, external, otheremployee, contractor, external (auditor, consultant…) or other.
position_idstring (uuid), can be null
preferred_namestring (up to 255), can be nullWhat they like to be called, if different.
work_emailstring (email) (up to 255), can be nullTheir work email address; how they are matched to logins in the products.

200 — OK. The record is in `data`, with its version in the `ETag` header.

Reply fields (24) — in data
idstring (uuid)The person's id in People (a UUID). Use it with /people/{person}.
display_namestringThe name shown everywhere in Kanishu.
preferred_namestring, can be nullWhat they like to be called, if different.
work_emailstringTheir work email address; how they are matched to logins in the products.
employee_numberstring, can be nullYour own employee number for them (e.g. from payroll or HR).
typestringemployee, contractor, external (auditor, consultant…) or other.
statusstringpre_joining (joining soon), active, on_leave, leaving (last working day set) or left.
joining_datestring (date)Their first working day.
last_working_datestring (date), can be nullTheir last working day, once they are leaving; their logins are switched off after it.
access_end_datestring (date), can be nullWhen their access to Kanishu products ends, if earlier or later than the last working day (e.g. contractors).
departmentobjectTheir department or team (id and name), from GET /people-organisation.
department.idstring (uuid)
department.namestring
positionobjectTheir job position (id and name).
position.idstring (uuid)
position.namestring
locationobjectTheir office or site (id and name).
location.idstring (uuid)
location.namestring
managerobject, can be nullTheir manager in People (id and display_name).
manager.idstring (uuid)
manager.display_namestring
created_atstring (date and time, ISO 8601)
updated_atstring (date and time, ISO 8601)

POST /api/v1/people/{person}/leave

Record a leaver (logins switched off after the last working day, or now if urgent) · scope people:write

ParameterInTypeAbout
person requiredpathinteger

Request fields (JSON body)

last_working_date requiredstring (date)Their last working day, once they are leaving; their logins are switched off after it.
reasonstring (up to 500), can be nullWhy they are leaving (kept in People's History).
urgentbooleantrue to switch their logins off now instead of after the last working day.

200 — The person, as GET /people/{person} returns them.

Reply fields (24) — in data
idstring (uuid)The person's id in People (a UUID). Use it with /people/{person}.
display_namestringThe name shown everywhere in Kanishu.
preferred_namestring, can be nullWhat they like to be called, if different.
work_emailstringTheir work email address; how they are matched to logins in the products.
employee_numberstring, can be nullYour own employee number for them (e.g. from payroll or HR).
typestringemployee, contractor, external (auditor, consultant…) or other.
statusstringpre_joining (joining soon), active, on_leave, leaving (last working day set) or left.
joining_datestring (date)Their first working day.
last_working_datestring (date), can be nullTheir last working day, once they are leaving; their logins are switched off after it.
access_end_datestring (date), can be nullWhen their access to Kanishu products ends, if earlier or later than the last working day (e.g. contractors).
departmentobjectTheir department or team (id and name), from GET /people-organisation.
department.idstring (uuid)
department.namestring
positionobjectTheir job position (id and name).
position.idstring (uuid)
position.namestring
locationobjectTheir office or site (id and name).
location.idstring (uuid)
location.namestring
managerobject, can be nullTheir manager in People (id and display_name).
manager.idstring (uuid)
manager.display_namestring
created_atstring (date and time, ISO 8601)
updated_atstring (date and time, ISO 8601)

POST /api/v1/people/{person}/move

Move a person (department, manager, position or location) from a date · scope people:write

ParameterInTypeAbout
person requiredpathinteger

Request fields (JSON body)

department_idstring (uuid), can be nullThe department or team they move to, from GET /people-organisation.
effective_date requiredstring (date)The date the move takes effect.
location_idstring (uuid), can be null
manager_idstring (uuid), can be nullTheir new manager's People id.
position_idstring (uuid), can be null

200 — The person, as GET /people/{person} returns them.

Reply fields (24) — in data
idstring (uuid)The person's id in People (a UUID). Use it with /people/{person}.
display_namestringThe name shown everywhere in Kanishu.
preferred_namestring, can be nullWhat they like to be called, if different.
work_emailstringTheir work email address; how they are matched to logins in the products.
employee_numberstring, can be nullYour own employee number for them (e.g. from payroll or HR).
typestringemployee, contractor, external (auditor, consultant…) or other.
statusstringpre_joining (joining soon), active, on_leave, leaving (last working day set) or left.
joining_datestring (date)Their first working day.
last_working_datestring (date), can be nullTheir last working day, once they are leaving; their logins are switched off after it.
access_end_datestring (date), can be nullWhen their access to Kanishu products ends, if earlier or later than the last working day (e.g. contractors).
departmentobjectTheir department or team (id and name), from GET /people-organisation.
department.idstring (uuid)
department.namestring
positionobjectTheir job position (id and name).
position.idstring (uuid)
position.namestring
locationobjectTheir office or site (id and name).
location.idstring (uuid)
location.namestring
managerobject, can be nullTheir manager in People (id and display_name).
manager.idstring (uuid)
manager.display_namestring
created_atstring (date and time, ISO 8601)
updated_atstring (date and time, ISO 8601)

Policies

GET /api/v1/policies

List policies · scope policies:read

ParameterInTypeAbout
fieldsquerystringOnly these fields of each record, comma-separated (e.g. `id,name`; nested: `owner.name`). `id` always comes back.
includequerystringRelated records in the same answer, comma-separated: `controls` — The framework controls the policy supports: framework, control_ref, title, rationale (why it supports it), reviewed_at (when an approver signed the mapping off, or null) (needs `controls:read`).

200 — Every matching record in one answer.

Reply fields (12) — each record in data
idinteger
titlestring
categorystringThe policy's category (e.g. IT_SECURITY).
version_labelstringThe published version (e.g. 1.0).
published_atstring (date and time, ISO 8601)When this version was published.
content_hashstringSHA-256 of the published text: if it changes, the policy changed.
controlslistOnly with ?include=controls. The framework controls the policy supports: framework, control_ref, title, rationale (why it supports it), reviewed_at (when an approver signed the mapping off, or null).
controls[].frameworkstringThe framework key (iso27001_2022, soc2_tsc, dpdp_2023, gdpr).
controls[].control_refstringThe control's reference in that framework (e.g. A.5.1).
controls[].titlestring
controls[].rationalestring, can be nullWhy the policy supports the control, if recorded.
controls[].reviewed_atstring (date and time, ISO 8601), can be nullWhen an approver signed the mapping off, or null.

Need fewer? Add ?fields= with the names you want, e.g. ?fields=title,category.

GET /api/v1/policies/{policy}

Get one of policies · scope policies:read

ParameterInTypeAbout
policy requiredpathinteger
fieldsquerystringOnly these fields of each record, comma-separated (e.g. `id,name`; nested: `owner.name`). `id` always comes back.
includequerystringRelated records in the same answer, comma-separated: `controls` — The framework controls the policy supports: framework, control_ref, title, rationale (why it supports it), reviewed_at (when an approver signed the mapping off, or null) (needs `controls:read`).

200 — OK. The record is in `data`, with its version in the `ETag` header.

Reply fields (13) — in data
idinteger
titlestring
categorystringThe policy's category (e.g. IT_SECURITY).
version_labelstringThe published version (e.g. 1.0).
published_atstring (date and time, ISO 8601)When this version was published.
content_hashstringSHA-256 of the published text: if it changes, the policy changed.
sectionsobjectThe policy text by section: purpose, scope, statements, responsibilities and related documents.
sections.purposestring
sections.scopestring
sections.statementslist of string
sections.responsibilitieslist of string
sections.relatedstring
controlslistOnly with ?include=controls. The framework controls the policy supports: framework, control_ref, title, rationale (why it supports it), reviewed_at (when an approver signed the mapping off, or null).

Need fewer? Add ?fields= with the names you want, e.g. ?fields=title,category.

Read

GET /api/v1/read-events

Who opened and who accepted each policy · scope reads:read

ParameterInTypeAbout
since_idqueryintegerReturn events after this id: pass the next_since_id from your last call. Start with 0.
limitqueryintegerAt most this many events (default 200, at most 500).
fieldsquerystringOnly these fields of each record, comma-separated (e.g. `id,name`; nested: `owner.name`). `id` always comes back.
includequerystringRelated records in the same answer, comma-separated: `policy` — The policy the event is about: id, title, category (needs `policies:read`).

200 — Events oldest first, one OPENED and one ACCEPTED at most per person and version. An empty list means you are up to date; keep next_since_id for the next call. People who have not read a policy are never listed.

Reply fields (8) — each record in data

Also in the answer: next_since_id.

idinteger
policy_idinteger
version_labelstringThe policy version the person read.
employee_refstringYour own id for the person, as you sent it when creating the read link.
employee_namestring, can be null
eventstring: OPENED, ACCEPTEDOPENED (the person opened the policy) or ACCEPTED (they clicked to accept it).
integrationstring, can be nullWhich token or screen sent the link.
occurred_atstring (date and time, ISO 8601)When it happened.

Need fewer? Add ?fields= with the names you want, e.g. ?fields=policy_id,version_label.

POST /api/v1/read-sessions

Send a person a policy to read and accept · scope reads:write

Request fields (JSON body)

policy_id requiredintegerA published policy (GET /policies).
employee_ref requiredstring (up to 255)Your own id for the person (employee number, email…). It comes back in the read-events feed.
employee_namestring (up to 255)Shown to the person and in the records. Optional.

201 — A link to open in the person's browser. It is for that person only, pinned to the version published now, and expires after 30 minutes. The person reads the policy and clicks to accept; both show up in GET /read-events.

Reply fields (2)
urlstring (uri)The link to open in the person's browser (for that person only).
expires_atstring (date and time, ISO 8601)When the link stops working.