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

Developers

The Kanishu API

Read and write your organisation's Kanishu data from your own systems — over HTTPS, with tokens your admins approve, limited to exactly the access each integration needs.

Products and addresses

Each product has its own address. Every path starts with /api/v1.

ProductBase addressEndpoints
ITSM https://itsm.kanishu.com/api/v1 3 Reference · OpenAPI
ITAM https://itam.kanishu.com/api/v1 4 Reference · OpenAPI
Vendor & Contract Management https://vcm.kanishu.com/api/v1 3 Reference · OpenAPI
Sales Lead Management (CRM) https://crm.kanishu.com/api/v1 3 Reference · OpenAPI
Policy Management https://policy.kanishu.com/api/v1 3 Reference · OpenAPI
Assurance https://assurance.kanishu.com/api/v1 3 Reference · OpenAPI
Password Vault https://vault.kanishu.com/api/v1 3 Reference · OpenAPI

Assurance and Password Vault offer only the API-access endpoints so far. Password Vault's items are encrypted on each person's device, so they are never available through the API.

People — the organisation's directory

People is shared by all your products, so its endpoints are on every product's address: /api/v1/people (list, filter by status, type, department and location, search), /api/v1/people/{id}, /api/v1/people-organisation (departments, positions, locations), and for changes POST /people, PATCH /people/{id}, and the lifecycle — POST /people/joiners, /people/{id}/move and /people/{id}/leave, which run the same steps as on screen (a leaver's logins are switched off, equipment collected). Scopes: people:read, people:write. See any product's reference, under People.

1. Get a token

Your organisation's plan must include API access. Then there are three ways, depending on who you are:

You don't use the product (a developer, an integration owner)

  1. Ask an admin of that product (someone who approves API access there) for API access, saying what it is for and what it needs to read or change. You must be in your organisation's People list with a work email — access is only for your organisation's own staff.
  2. The admin chooses you from People under API access → Give an employee API access, picks the scopes (read and write are separate) and how long it lasts. You need no login and take no seat; the token is sponsored by that admin.
  3. You receive an email with a one-time link (valid 48 hours). Open it to see the token — it is shown once. The token itself is never written in an email or shown to the admin. If the link says it was already used and you didn't open it, tell the admin straight away so they revoke the token.

You use the product

  1. In the product, open API access and request access: what it's for, the scopes it needs (e.g. assets:read), and why.
  2. A second person with approval rights approves it — and may narrow the scopes. They can also require signed requests or limit the token to IP addresses you name.
  3. Reveal the token (and, if required, its signing secret). It is shown once; Kanishu keeps only a fingerprint. Lost it? Request again.

However you got it: every call is recorded with the token and shown under API activity in the product (to you for your tokens, to admins for all). Admins can revoke a token at any time, a token unused for a while can switch itself off, and a token stops when the person it acts for leaves.

A token reaches only your organisation and only the scopes approved for it.

2. Your first call

curl https://itam.kanishu.com/api/v1/assets?per_page=5 \ -H "Authorization: Bearer $KANISHU_TOKEN" \ -H "Accept: application/json"

Every request needs Authorization: Bearer <token> and Accept: application/json (plus Content-Type: application/json when sending a body). Never put a token in the address — such calls are refused (400 token_in_url), because addresses end up in logs. HTTPS only.

3. Responses

JSON, with snake_case field names. A record is {"data": {…}}; a list adds meta and links. Times are UTC (2026-10-27T09:30:00Z); an empty field is null, never missing.

Every response carries X-Request-Id — quote it to support (you may send your own, up to 64 characters). Errors always look like this:

{ "error": { "code": "validation_failed", "message": "The name field is required.", "details": { "fields": { "name": ["The name field is required."] } }, "request_id": "ae4d70da-9678-4f16-a7e4-3f03b36085e4" } }

All codes, with what to do about each: Error codes.

4. Lists

  • Pages: ?page=2&per_page=50 (25 by default, at most 100). meta has page, per_page, total, last_page; links has first, prev, next, last.
  • Filters: ?filter[status]=active; a comma means "any of": filter[status]=active,in_stock. Each list accepts only its own filters — anything else is 400 invalid_filter with the allowed ones listed.
  • Sorting: ?sort=-created_at,name (- = newest first). Search: ?q=laptop.
  • Only the fields you need (any GET): ?fields=name,status returns just those fields of each record (id always comes back); fields inside an object or list use a dot: ?fields=name,assigned_to.email. A name the answer doesn't have is 400 invalid_fields, listing the ones it does. Each endpoint in the API reference lists its reply fields and, for creating and changing, its request fields.
  • Related records in the same answer: ?include=contact,stage adds them to each record (one level). Each endpoint lists what it offers under include; an included record needs its own scope too (e.g. contacts:read) and shows only what the token's owner may see. Combine with fields: ?include=contact&fields=title,contact.email. Anything not offered is 400 invalid_include.

5. Writing safely

  • Create with POST (201 and the record), change with PATCH — fields you don't send are left alone, null clears one — and delete with DELETE (204).
  • Safe retries: send an Idempotency-Key (a UUID you make) on every POST. Repeating the same request with the same key within 24 hours returns the first answer (Idempotent-Replayed: true) instead of creating a duplicate.
  • Not overwriting someone else's change: each record comes with its version in the ETag header. Send it back as If-Match on PATCH/DELETE; if the record changed in the meantime you get 412 version_conflict and can re-read it.
  • Every change made through the API appears in the record's History like one made on screen, with the token as the actor. Plan limits apply exactly as on screen (402 limit_reached).

6. Limits

  • Burst limit per token (server protection): too many calls in a minute gives 429 rate_limited — wait for Retry-After. Every response has RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset.
  • Daily quota per organisation, per product area, set by your plan and shared by all your tokens. Responses carry Kanishu-Quota-Limit, Kanishu-Quota-Remaining and Kanishu-Quota-Reset; once used up, 429 quota_exceeded until midnight (India time).

7. Signed requests

When a token requires them (your admin decides, for sensitive access), every call also carries:

Kanishu-Signature: t=<unix seconds>,n=<nonce, 16–64 characters>,v1=<hex HMAC-SHA256>

The HMAC uses the token's signing secret over five lines joined by \n: the time, the nonce, the method in capitals, the path with its query string, and the SHA-256 (hex) of the body (empty body = SHA-256 of nothing). The time must be within 5 minutes of ours, and each nonce works once.

// PHP $t = time(); $n = bin2hex(random_bytes(16)); $payload = "$t\n$n\nGET\n/api/v1/assets?per_page=5\n" . hash('sha256', ''); $header = "t=$t,n=$n,v1=" . hash_hmac('sha256', $payload, $signingSecret); // Node.js const crypto = require('crypto'); const t = Math.floor(Date.now() / 1000), n = crypto.randomBytes(16).toString('hex'); const body = ''; const payload = [t, n, 'GET', '/api/v1/assets?per_page=5', crypto.createHash('sha256').update(body).digest('hex')].join('\n'); const header = `t=${t},n=${n},v1=` + crypto.createHmac('sha256', signingSecret).update(payload).digest('hex');

A missing, wrong or old signature is 401 bad_signature, with the reason in message.

8. Versions

The version is in the path. Within v1 we only add — new fields, endpoints, optional parameters and error codes — never remove or rename anything, or change what a field means. A breaking change would be v2, and v1 would keep working for at least 12 months, announced here and with Deprecation/Sunset response headers. Write your integration to ignore fields it doesn't know.

Coming later

Webhooks (Kanishu calling your system when something happens) and bulk endpoints are planned; they are not available yet.