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.
| Product | Base address | Endpoints | |
|---|---|---|---|
| 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)
- 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.
- 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.
- 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
- In the product, open API access and request access: what it's for, the scopes it needs (e.g.
assets:read), and why. - 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.
- 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).metahaspage, per_page, total, last_page;linkshasfirst, 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 is400 invalid_filterwith the allowed ones listed. - Sorting:
?sort=-created_at,name(-= newest first). Search:?q=laptop. - Only the fields you need (any GET):
?fields=name,statusreturns just those fields of each record (idalways comes back); fields inside an object or list use a dot:?fields=name,assigned_to.email. A name the answer doesn't have is400 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,stageadds them to each record (one level). Each endpoint lists what it offers underinclude; 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 is400 invalid_include.
5. Writing safely
- Create with
POST(201 and the record), change withPATCH— fields you don't send are left alone,nullclears one — and delete withDELETE(204). - Safe retries: send an
Idempotency-Key(a UUID you make) on everyPOST. 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
ETagheader. Send it back asIf-MatchonPATCH/DELETE; if the record changed in the meantime you get412 version_conflictand 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 forRetry-After. Every response hasRateLimit-Limit,RateLimit-RemainingandRateLimit-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-RemainingandKanishu-Quota-Reset; once used up,429 quota_exceededuntil 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.