Quickstart
The Keepnet API lets you automate platform operations: pull reports, manage users, onboard customers, and integrate with SIEM, SOAR, or identity systems.
You can use the Keepnet API to:
Pull campaign reports (phishing, smishing, quishing, vishing, callback)
Export training reports, gamification data, and executive summaries
Add target users and enroll them in training
List and manage companies (Reseller)
Export audit logs to SIEM
…and more, all via REST calls with OAuth 2.0 Client Credentials.
Use the API from AI assistants (Cursor, Claude, ChatGPT, etc.) via MCP: Use the API with AI assistants (MCP) →
Getting started
You need a Keepnet platform account with API access. Generate Client ID and Client Secret from Company → Company Settings → REST API before making any API calls.
Name
A label for this credential set (e.g. prod-integration, siem-connector)
Client Role
Company Admin for full access, or a custom role with limited privileges
IP Restriction
Optionally restrict access to specific IP addresses
Status
Set to Active
The Client Secret is shown only once. Copy and store it securely immediately after you generate it — it cannot be retrieved later.
Request an access token
Keepnet API uses OAuth 2.0 Client Credentials. Every request requires a Bearer token in the Authorization header.
Endpoint: POST /connect/token
Send a POST request with form-encoded body:
curl -X POST https://api.keepnetlabs.com/connect/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "scope=api1"Response:
{
"access_token": "eyJ...",
"expires_in": 3600,
"token_type": "Bearer",
"scope": "api1",
"permissions": ["tags/search|POST", "companies/search|POST", "..."]
}Include access_token in every API request as Authorization: Bearer <token>. The optional permissions array lists endpoints your credential can call (e.g. companies/search|POST).
const response = await fetch('https://api.keepnetlabs.com/connect/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
scope: 'api1',
}),
});
const { access_token } = await response.json();
// Use: Authorization: Bearer ${access_token}Integration tools (Zapier, Make, n8n, Postman, etc.)
The token endpoint accepts only application/x-www-form-urlencoded. Do not send a JSON body or use "Raw" with Content-Type: application/json — that returns a 500 Internal Server Error. In your tool, choose Form (or form-urlencoded) as the body type and send the fields: grant_type, client_id, client_secret, scope.
Test it — step by step
Authorize is not on this page; it is in the Endpoints section. Open Endpoints in the left sidebar → pick an endpoint (e.g. Company → Retrieves a list of all companies) → in the right panel click the lock icon Authorize → enter Client ID and Client Secret → click Authorize. The token is fetched and applied to all requests. Then click Send in the same panel to send the request.
GET /api/companies/my: Endpoints → Company → Retrieves the companies which can be simulated by user → Send. No body.
POST /api/companies/search: Endpoints → Company → Retrieves a list of all companies → Body is pre-filled → Send. Reseller credential required.
Alternatively, get a token from the POST /connect/token block on this page, copy access_token from the response, and paste it into the Bearer field in Endpoints instead of using Authorize.
Make your first API call
Verify your token and company access with GET /api/companies/my — returns your company (Company Admin) or companies you manage (Reseller). No request body, no extra parameters.
curl -X GET "https://api.keepnetlabs.com/api/companies/my" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json"If successful, you'll get a data array with your company details (id, name, etc.). This confirms:
Token is valid
Credentials have API access
You can fetch your own company data
Test it — quick checklist
The Authorize button is not on the Quickstart page; it appears in the right panel when you open an endpoint under Endpoints (left sidebar). Order:
1
Endpoints → open any endpoint (e.g. Company → Retrieves a list…) → Authorize (lock icon) → enter Client ID + Client Secret → click Authorize
Token is fetched and applied to all requests
2
GET /api/companies/my (Company) → Send
Returns your company (Company Admin) or companies you manage (Reseller)
3
POST /api/companies/search (Company) → Body pre-filled → Send
Company list with license details (Reseller credential required)
Base URL and response format
Base URL: https://api.keepnetlabs.com
All API responses include an isSuccess field. When isSuccess is false, check the messages array for error details.
isSuccess
boolean
Indicates whether the request succeeded
data
object
Response payload when successful
messages
array
Error or validation messages when failed
Common conventions
Pagination
Search endpoints use pageNumber, pageSize, orderBy, ascending, filter in the request body
Search request body
Do not send an empty body for search endpoints. Always include at least pageNumber, pageSize, orderBy, ascending, and filter (or the structure shown in the endpoint). Empty or missing body can cause errors or unreliable results in automation tools.
Filter
Do not send filter: null or null inside filter fields on search endpoints that expect a filter object — use a minimal object: "Condition": "AND", "SearchInputTextValue": "" (then add FilterGroups / items only if the endpoint requires them). searchInputTextValue must be "", not null.
Sorting
orderBy must be a non-null string (e.g. CreateTime, Email). Set ascending explicitly (true / false); do not rely on undocumented defaults.
Company scope
Most endpoints require a company context. Company Admin: automatic. Reseller: include Company ID (header/path/query)
Integration and automation
When calling the API from automation platforms (Zapier, Make, n8n, custom scripts, etc.), follow these rules to avoid common errors:
Token (POST /connect/token)
Body must be form-encoded (application/x-www-form-urlencoded). Use the Form body type in your tool; send grant_type, client_id, client_secret, scope.
Sending JSON or Raw with Content-Type: application/json returns 500 Internal Server Error.
Search endpoints (e.g. POST /api/companies/search)
Send pageNumber, pageSize, explicit non-null orderBy, ascending, and a minimal filter (Condition + SearchInputTextValue: ""). Do not use filter: null or null filter fields.
400 / 500 or INPUT_ERROR.
What the token contains
The access token is a JWT. Decode it to read company context, role, and other values — useful when endpoints require Company ID in the path, header, or query.
To decode: Paste the token at jwt.io (signature verification optional) or Base64URL-decode the middle part (between the two dots).
Company context
user_company_resourceid
Company ID — use in X-KEEPNET-Company-Id, path /api/.../companies/{id}/..., or ?companyId=
xC5kfGz7w2Nz
user_company_name
Company name
ACME LLC
user_company_id
Numeric company ID
1
user_company_logopath
Company logo URL
https://api.keepnetlabs.com/companylogo/...
user_company_industry_name
Industry (e.g. Technology)
Technology
user_company_parentcompany_resourceid
Parent/MSSP company ID — Reseller only, empty for Company Admin
xC5kfGz7w2Nz (Reseller) or empty
user_company_parentcompany_name
Parent company name — Reseller only
ACME Corp
Role and access
role
User role
Company Admin
Reseller
company_admin_access
Can manage own company
true
true
reseller_access
Can manage multiple companies
false
true
root_access
Platform root/admin
false
false
scope
API scope
["api1"]
["api1"]
Token metadata
exp
Expiry (Unix timestamp)
1772935488
iat
Issued at (Unix timestamp)
1772931888
client_id
Client ID used to obtain the token
xxxxxxxxxxxxxxxx
Who can use the API
Company Admin
Full access to your company's data — no Company ID needed
Reseller
Cross-company management — list companies, onboard customers, pull reports per company using Company ID
Custom role
Scoped to specific products or actions based on role definition
Token expiry and errors
Tokens expire after 1 hour. No refresh token — request a new one when the current token expires.
400 Bad Request — invalid_client
Wrong or placeholder credentials
Use real credentials from Company → Company Settings → REST API
401 Unauthorized
Missing or invalid token
Re-authenticate and retry
403 Forbidden
Insufficient role permissions
Check the Client Role in platform settings
500 Internal Server Error (on token)
Token request sent with JSON or wrong Content-Type
Use form-encoded body only: Content-Type: application/x-www-form-urlencoded and Form body type in your tool.
429 Too Many Requests
Rate limit exceeded
Back off and retry after a delay
Reseller: scope by Company ID
If your credential has the Reseller role, include Company ID when calling company-scoped endpoints:
Header:
X-KEEPNET-Company-Id: {companyId}(when supported)Path:
/api/.../companies/{companyId}/...Query:
?companyId={companyId}
Company IDs are returned by POST /api/companies/search. For a full explanation and usage in report and user endpoints, see Scope API requests to a customer →. For the list: List companies with license details →.
Keep credentials secure
Do: Store credentials in environment variables or a secrets manager. Enable IP Restriction if your integration runs from a fixed IP. Use a custom role scoped to only the endpoints you need.
Don't: Hard-code client_id or client_secret in source code. Don't commit credentials to version control.
Explore the API
List companies (Reseller)
Scope requests to a customer
Export customer list for billing
View customer's training enrollments
View customer's simulation campaigns
Last updated