Developers
Build on naasflow
A read-only REST API and signed webhooks let your own systems stay in sync with your naasflow workspace — employees, leave, payroll, hiring, and billing. Authenticate with a scoped API key from Settings → Integrations.
Authentication
Create an API key under Settings → Integrations → API keys. The key (nf_live_…) is shown once. Send it as a bearer token on every request:
curl https://app.naasflow.com/api/v1/employees \
-H "Authorization: Bearer nf_live_your_key_here"Each key carries one or more scopes. Requests are rate limited to 120 requests/minute per key. Available scopes:
Endpoints
| Method | Path | Scope |
|---|---|---|
| GET | /api/v1/employeesList employees | employees:read |
| POST | /api/v1/employeesCreate an employee | employees:write |
| GET | /api/v1/employees/{id}Get one employee | employees:read |
| PATCH | /api/v1/employees/{id}Update an employee | employees:write |
| GET | /api/v1/departmentsList departments | departments:read |
| POST | /api/v1/departmentsCreate a department | departments:write |
| GET | /api/v1/designationsList designations | departments:read |
| POST | /api/v1/designationsCreate a designation | departments:write |
| GET | /api/v1/leave-requestsList leave requests | leave:read |
| GET | /api/v1/payroll/runsList payroll runs | payroll:read |
| GET | /api/v1/payroll/runs/{id}Get one payroll run | payroll:read |
| GET | /api/v1/eventsList emitted events | events:read |
Pagination & responses
List endpoints accept ?limit= (1–100, default 50) and an opaque ?cursor=. Responses are wrapped in a stable envelope:
{
"data": [ /* … */ ],
"pagination": { "next_cursor": "eyJ…", "has_more": true }
}Errors use a consistent shape with the appropriate HTTP status:
{ "error": { "code": "forbidden", "message": "This key is missing the 'payroll:read' scope." } }Webhooks
Register HTTPS endpoints under Settings → Integrations → Webhooks and subscribe to events. naasflow POSTs a signed JSON envelope and retries failures with exponential backoff. Subscribable events include:
Verify the X-Naasflow-Signature header before trusting a payload. The signed value is {timestamp}.{rawBody}, HMAC-SHA256 with your endpoint's signing secret:
// Node.js
import crypto from "node:crypto";
function verify(req, secret) {
const ts = req.headers["x-naasflow-timestamp"];
const sig = req.headers["x-naasflow-signature"]; // "v1=<hex>"
const expected =
"v1=" + crypto.createHmac("sha256", secret)
.update(ts + "." + req.rawBody)
.digest("hex");
return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}# Python
import hmac, hashlib
def verify(headers, raw_body, secret):
ts = headers["X-Naasflow-Timestamp"]
sig = headers["X-Naasflow-Signature"] # "v1=<hex>"
expected = "v1=" + hmac.new(
secret.encode(), f"{ts}.{raw_body}".encode(), hashlib.sha256
).hexdigest()
return hmac.compare_digest(sig, expected)