Welcome to the API documentation for Nimbly Technologies. Our mission is to make your integration experience seamless and efficient. Whether you're a seasoned developer or just getting started, this documentation is your gateway to understanding and leveraging the full potential of Nimbly's API. Dive in to explore endpoints, authentication methods, data formats, and everything you need to successfully integrate with our services.
To access our Nimbly API, you need to authenticate using a secret token as an API key. API keys are a simple and secure way to identify your application when making requests to our API.
To obtain API keys for authentication, please reach out to our team. Once your request for API keys has been approved, we will securely send them to you via email, ensuring that you have the necessary credentials to access our API.
Your API keys are sensitive credentials. Avoid sharing them publicly to maintain the confidentiality of your data and the security of your API resources.
For authenticating your API requests, include your API key in the request headers as shown below:
GET /reports
x-api-key: YOUR_API_KEY
Replace YOUR_API_KEY with the actual API key you received from our team.
This x-api-key header is used to allow the server to identify and authorize your organization account. Please note that any API call made without including the 'x-api-key' header will result in a failed request.
The API base URL is now:
https://api.hellonimbly.com/v1.0/public
If your integration still uses the previous cloudfunctions.net base URL, please migrate: only the base URL changes, while every path, parameter, response and your API key stay exactly the same. The old base URL is deprecated - it keeps working during the deprecation window, but new capabilities (such as the MCP server below) are only available on the new base URL.
Our Nimbly API use rate limiter to ensure equitable access to our API resources while maintaining system stability. This document outlines our rate limiting policies, how to handle rate limit errors, and tips for optimizing your API usage within these limits.
Our rate limiter enforces the following rate limiting policy:
When you exceed the rate limit, our API will respond with a 429 Too Many Requests status code. This indicates that you have reached the maximum allowed request rate. The response will include additional information in the headers for your reference:
X-RateLimit-Limit: The total number of requests allowed per second.X-RateLimit-Remaining: The number of requests remaining in the current rate-limiting window.Here's an example of a rate-limited response:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
X-RateLimit-Limit: 3
X-RateLimit-Remaining: 0
{
"message": "Limit Exceeded"
}
To ensure smooth API interactions and avoid rate-limiting errors:
By following these guidelines, you can work effectively within our rate limits and ensure a smooth experience while using the Nimbly API.
The same data this API exposes is also available to AI assistants through a Model Context Protocol server, so tools like Claude, Claude Code and Cursor can answer questions about your sites, audits and issues directly.
The MCP server is served over Streamable HTTP at:
POST https://api.hellonimbly.com/v1.0/public/mcp
Authenticate with the same API key you use for the REST endpoints, either as an x-api-key header or as Authorization: Bearer YOUR_API_KEY for clients that only offer a bearer-token field. The endpoint holds no session state and accepts POST only; GET and DELETE return 405.
The server implements MCP revision 2026-07-28, where each request is self-contained and no initialize handshake is needed. Clients built against earlier revisions are served too and need no special configuration, so any current MCP client works as-is.
Every tool is read-only and scoped to the organization that owns the API key.
list_sites, get_site: locations, their departments, city and timezone.list_reports, get_report: submitted audit reports, including per-question answers and scores.list_issues, get_issue, get_issue_status_history: findings and corrective actions, with their full status trail.list_users, get_user: active users, their roles and coverage.list_questionnaires: audit checklists and their question counts.list_schedules: planned audits in a date range with completion percentages.list_departments: departments defined in your organization.For Claude Code, add the server from your terminal:
claude mcp add --transport http nimbly https://api.hellonimbly.com/v1.0/public/mcp --header "x-api-key: YOUR_API_KEY"
For Claude Desktop, Cursor and other clients that read a JSON config file, add:
{
"mcpServers": {
"nimbly": {
"type": "http",
"url": "https://api.hellonimbly.com/v1.0/public/mcp",
"headers": { "x-api-key": "YOUR_API_KEY" }
}
}
}
Tool calls draw on the same per-organization rate limit as the REST endpoints, so one tool call costs the same as one REST request. When the limit is exhausted the tool returns an error result telling the assistant to retry shortly, rather than failing the whole conversation.
Simplify your API interaction with our Exported Postman Collections. This collection contains a curated set of API endpoints and request examples that will accelerate your development and integration processes.
Simply follow these steps to start interact with our Nimbly API
Fetches report analytics based on the specified metric.
| x-api-key required | string |
| startDate required | string <date> |
| endDate required | string <date> |
| metric required | string Enum: "rcr" "report-overview" "report-insight-overview" "reportList" "reportChart" "reportPieChart" |
| viewBy | string Enum: "site" "completeCount" "missedCount" "rcr" "completionTime" "submittedCount" "reportStatus" "reportType" |
| groupBy | string Enum: "site" "department" "user" "questionnaire" "date" "siteGroup" "reportStatus" "reportType" |
| groupByID | string |
| sortBy | string |
| sortDirection | string Enum: "asc" "desc" |
| limit | number |
| period | string Enum: "DAILY" "WEEKLY" "MONTHLY" "QUARTERLY" "YEARLY" |
| siteIDs | Array of strings |
| departmentIDs | Array of strings |
| userIDs | Array of strings |
| questionnaireIDs | Array of strings |
| reportStatus | Array of strings |
{- "startDate": "2026-01-01",
- "endDate": "2026-01-31",
- "metric": "rcr",
- "viewBy": "site",
- "groupBy": "site",
- "groupByID": "string",
- "sortBy": "string",
- "sortDirection": "asc",
- "limit": 10,
- "period": "DAILY",
- "siteIDs": [
- "string"
], - "departmentIDs": [
- "string"
], - "userIDs": [
- "string"
], - "questionnaireIDs": [
- "string"
], - "reportStatus": [
- "string"
]
}{- "message": "success",
- "data": { }
}Fetches issue analytics based on the specified metric.
| x-api-key required | string |
| startDate required | string <date> |
| endDate required | string <date> |
| metric required | string Enum: "issue-voc" "irr" "health" "issue-overview" "issue-insight-overview" "heatmap" "issueList" "issueInsightList" "issueChart" "issuePieChart" "issueReoccurred" |
| viewBy | string Enum: "site" "irr" "openIssueCount" "irrTime" "issueFlag" "issueRedFlag" |
| groupBy | string Enum: "site" "department" "user" "questionnaire" "category" "issueSeverity" "issueStatus" "issuePriority" "issueSecondaryStatus" "approvalStatus" |
| groupByID | string |
| primaryStatus | Array of strings Items Enum: "open" "in-progress" "in-review" "blocked" "resolved" |
| priority | Array of strings Items Enum: "high" "medium" "low" |
| categories | Array of strings |
{- "startDate": "2026-01-01",
- "endDate": "2026-01-31",
- "metric": "issue-voc",
- "viewBy": "site",
- "groupBy": "site",
- "groupByID": "string",
- "primaryStatus": [
- "open"
], - "priority": [
- "high"
], - "categories": [
- "string"
]
}{- "message": "success",
- "data": {
- "irr": 0,
- "resolvedIssues": 0,
- "openIssuesCount": 0,
- "openIssuesPercentage": 0,
- "totalIssues": 0,
- "avgIssueResolutionTime": "string",
- "trend": "upward",
- "trendDifference": 0
}
}Fetches real-time platform statistics overview.
| x-api-key required | string |
{- "message": "success",
- "data": {
- "schedulesDueToday": 0,
- "reportsCompletedToday": 0,
- "issuesOpen": 0,
- "skuSchedules": 0,
- "availableStorage": 0,
- "todaysGalleryCount": 0
}
}Search sites by name. Returns siteID, name, and city.
| search required | string Site name or partial name (case-insensitive) |
| page | number Default: 1 |
| limit | number <= 100 Default: 10 |
| x-api-key required | string |
{- "message": "success",
- "data": {
- "docs": [
- {
- "siteID": "string",
- "name": "string",
- "city": "string"
}
], - "totalDocs": 0,
- "limit": 0,
- "page": 0,
- "totalPages": 0
}
}Search active users by name or email.
| search required | string User name, partial name, or email |
| page | number Default: 1 |
| limit | number <= 100 Default: 10 |
| x-api-key required | string |
{- "message": "success",
- "data": {
- "docs": [
- {
- "userID": "string",
- "displayName": "string",
- "email": "string",
- "role": "string",
- "status": "active",
- "phoneNumber": "string",
- "language": "string",
- "photoURL": "string"
}
], - "totalDocs": 0,
- "limit": 0,
- "page": 0,
- "totalPages": 0
}
}Search questionnaires by title. Returns questionnaireIndexID and title.
| search required | string Questionnaire title or partial title |
| page | number Default: 1 |
| limit | number <= 100 Default: 10 |
| x-api-key required | string |
{- "message": "success",
- "data": {
- "docs": [
- {
- "questionnaireIndexID": "string",
- "title": "string",
- "latest": "string",
- "versions": [
- "string"
], - "questionCount": 0,
- "disabled": true,
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}
], - "totalDocs": 0,
- "limit": 0,
- "page": 0,
- "totalPages": 0
}
}Nimbly API for issue's related usecase. Issues are generated based on your report's answer. One example for this usecase is to get list of all issues created within your organization.
Returns list of your issue's data. The returned data will be based on the query, using pagination format.
| site_name | string (optional) Example: site_name=Store A Multiple Example: Filter based on the site name. Multiple site name query is supported. |
| created_dept | string (optional) Example: created_dept=Department A Multiple Example: Filter based on the reporter department name. Multiple reporter department name query is supported. |
| assigned_dept | string (optional) Example: assigned_dept=Department A Multiple Example: Filter based on the assigned department name. Multiple assigned department name query is supported. |
| qnr_name | string (optional) Example: qnr_name=FnB - Coffee Shop Multiple Example: Filter based on the questionnaire name. Multiple questionnaire name query is supported. |
| title | string (optional) Example: title=Food items stored properly Multiple Example: Filter based on the issue's title. Multiple issue's title query is supported. |
| category_name | string (optional) Example: category_name=Food/Beverage Safety Multiple Example: Filter based on the issue's category name. Multiple category name query is supported. |
| created_by | string (optional) Example: created_by=Auditor A Multiple Example: Filter based on the issue's creator name. Multiple issue's creator name query is supported. |
| assigned_to | string (optional) Example: assigned_to=Auditor A Multiple Example: Filter based on the issue's assignee name. Multiple issue's assignee name query is supported. |
| member | string (optional) Example: member=Auditor A Multiple Example: Filter based on the issue's member name. Multiple issue's member name query is supported. |
| status | string (optional) Enum: "open" "resolved" "expired" "blocked" "in-review" "in-progress" Example: status=open Multiple Example: Filter based on the issue's status. Multiple issue's status query is supported. |
| severity | string (optional) Enum: "red" "yellow" Example: severity=yellow Multiple Example: Filter based on the issue's severity. Multiple issue's severity query is supported. |
| priority | string (optional) Enum: "low" "medium" "high" Example: priority=medium Multiple Example: Filter based on the issue's priority. Multiple issue's priority query is supported. |
| origin | string (optional) Enum: "report" "report-adhoc" "report-scheduled" "manual-addition" "customer-feedback" Example: origin=report-scheduled Multiple Example: Filter based on the issue's origin. Multiple issue's origin query is supported. |
| date_filter_type | string (optional) Enum: "created_date" "resolved_date" "due_date" Example: date_filter_type=created_date An enum that indicates the date type filter. It will affect on how
|
| start_date | string (optional) <date> Example: start_date=2023-10-23 String with format of |
| end_date | string (optional) <date> Example: end_date=2023-11-23 String with format of |
| sort_by | string (optional) Enum: "created_date" "resolved_date" "due_date" Example: sort_by=created_date An enum that indicates the date where sorting is based on.
|
| sort_type | string (optional) Enum: "asc" "desc" Example: sort_type=asc An enum that indicates the sorting type. It will affect on how
|
| limit | number (optional) Example: limit=100 Limit number on how many data will be returned. Limit can range between 1 and 100, with default number is 100. |
| offset | number (optional) Offset number on how many data will be skipped before returning the next data. Offset can range between 0 and total sites, with default number is 0. |
| x-api-key required | string Example: 4921f457d0277b412e13dc3e38df27e8 |
{- "message": "SUCCESS",
- "data": {
- "docs": [
- {
- "issueID": "aeacd1a9-89b6-4249-beda-eb52089df8e3",
- "createdAt": "2023-08-29T05:09:59.609Z",
- "answer": 3,
- "assignedDepartments": [
- "departmentA",
- "departmentB"
], - "assignedTo": "User Sample",
- "category": "Category A",
- "createdBy": "User Sample",
- "resolvedBy": "User Sample",
- "status": "open",
- "resolvedAt": "2023-08-29T05:09:59.609Z",
- "dueAt": "2023-08-29T05:09:59.609Z",
- "siteName": "Sample Site",
- "questions": "This is sample questions A.",
- "createdDepartment": "Sample Department",
- "questionnaire": "Sample Questionnaire",
- "priority": "Low",
- "severity": "yellow",
- "origin": "report"
}
], - "limit": 100,
- "offset": 0,
- "totalDocs": 100,
- "totalPage": 1
}
}Returns a single issue detail by its unique identifier.
| issueID required | string <uuid> Unique identifier of the issue (UUID) |
| x-api-key required | string |
{- "message": "success",
- "data": {
- "issueID": "9605a333-a828-49e5-9472-38fe6cde72f2",
- "issueSequenceID": "string",
- "status": "open",
- "secondaryStatus": "string",
- "priority": "string",
- "priorityV2": {
- "key": "string",
- "name": "string"
}, - "severity": "red",
- "category": "string",
- "type": "string",
- "questionText": "string",
- "site": {
- "key": "string",
- "name": "string"
}, - "department": "string",
- "assignedDepartments": [
- "string"
], - "questionnaire": {
- "key": "string",
- "name": "string"
}, - "assignedTo": {
- "key": "string",
- "name": "string",
- "email": "string",
- "photoURL": "string"
}, - "createdBy": {
- "key": "string",
- "name": "string",
- "email": "string",
- "photoURL": "string"
}, - "resolvedBy": {
- "key": "string",
- "name": "string",
- "email": "string",
- "photoURL": "string"
}, - "dueDate": "2019-08-24T14:15:22Z",
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z",
- "resolvedAt": "2019-08-24T14:15:22Z",
- "startDate": "2019-08-24T14:15:22Z",
- "endDate": "2019-08-24T14:15:22Z",
- "reportID": "string",
- "attachments": [
- {
- "id": "string",
- "fileName": "string",
- "fileType": "string",
- "mimeType": "string",
- "signedURL": "string"
}
]
}
}Returns the status change audit trail for an issue.
| issueID required | string <uuid> Unique identifier of the issue (UUID) |
| x-api-key required | string |
{- "message": "success",
- "data": [
- {
- "issueID": "9605a333-a828-49e5-9472-38fe6cde72f2",
- "type": "string",
- "status": "string",
- "message": "string",
- "messageType": "string",
- "createdBy": "string",
- "createdByName": "string",
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}
]
}Creates a rate limit record for the authenticated organization.
| x-api-key required | string |
| limit required | number Maximum requests per minute |
{- "limit": 20
}{- "message": "success",
- "data": "DONE"
}Returns the current rate limit configuration for the authenticated organization.
| x-api-key required | string |
{- "message": "success",
- "data": {
- "limit": 0,
- "disabled": true,
- "organizationID": "string",
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}
}Updates the rate limit configuration. Provide at least one of limit or disabled.
| x-api-key required | string |
| limit | number Maximum requests per minute |
| disabled | boolean Whether rate limiting is disabled |
{- "limit": 0,
- "disabled": true
}{- "message": "success",
- "data": "DONE"
}Nimbly API for report's related usecase. Reports are generated when you do a checklist in the form of questionnaire from the nimbly app. One example for this usecase is to get list of all reports generated within your organization.
| site_name | string (optional) Example: site_name=Store A Multiple Example: Filter based on the site name. Multiple site name query is supported. |
| dept_name | string (optional) Example: dept_name=Department A Multiple Example: Filter based on the department name. Multiple department name query is supported. |
| qnr_name | string (optional) Example: qnr_name=FnB - Coffee Shop Multiple Example: Filter based on the questionnaire name. Multiple questionnaire name query is supported. |
| user_name | string (optional) Example: user_name=Auditor A Multiple Example: Filter based on the user/auditor name. Multiple user name query is supported. |
| date_filter_type | string (optional) Enum: "scheduled_date" "submitted_date" Example: date_filter_type=scheduled_date An enum that indicates the date type filter. It will affect on how
|
| start_date | string (optional) <date> Example: start_date=2023-10-23 String with format of |
| end_date | string (optional) <date> Example: end_date=2023-11-23 String with format of |
| pagination_type | string (optional) Enum: "record" "site" Example: pagination_type=record An enum that indicates pagination type. It will affect how data is divided using the
|
| limit | number (optional) Example: limit=100 Limit number on how many data will be returned. If |
| offset | number (optional) Offset number on how many data will be skipped before returning the next data. If |
| x-api-key required | string Example: 4921f457d0277b412e13dc3e38df27e8 |
{- "message": "SUCCESS",
- "data": {
- "docs": [
- {
- "reportID": "6da66c81bf95904dbb1e63a0fc846ce4_2023-08-29_1693285730139",
- "submittedDate": "2023-08-29T05:09:35.474Z",
- "startDateTime": "2023-08-29T05:08:39.000Z",
- "endDateTime": "2023-08-29T05:09:34.667Z",
- "scheduledDate": "2023-08-29",
- "submittedBy": "User Sample",
- "auditorName": "User Sample",
- "status": "complete",
- "siteName": "Sample Site",
- "siteTimezone": "Asia/Jakarta",
- "departmentName": "Sample Department",
- "questionnaireDetail": [
- {
- "questionText": "This is a sample question for Yes/No",
- "response": "green-flag"
}
]
}
], - "limit": 100,
- "offset": 0,
- "totalDocs": 100,
- "totalPage": 1
}
}Returns a single report detail by its unique identifier.
| reportID required | string MongoDB identifier of the report |
| x-api-key required | string |
{- "message": "success",
- "data": {
- "reportID": "string",
- "scheduleID": "string",
- "auditName": "string",
- "siteName": "string",
- "siteID": "string",
- "datetimeIn": "2019-08-24T14:15:22Z",
- "flagCount": {
- "red": 0,
- "green": 0,
- "yellow": 0
}, - "signatures": [
- { }
], - "emailTargets": [
- "string"
]
}
}Nimbly API for site's related usecase. Sites are locations where reports and issues are generated within your organization. One example for this usecase is to get list of all sites created within your organization.
Returns list of your site's data. The returned data will be based on the query, using pagination format.
| site_name | string (optional) Example: site_name=Store A Multiple Example: Filter based on the site name. Multiple site name query is supported. |
| dept_name | string (optional) Example: dept_name=Department A Multiple Example: Filter based on the department name. Multiple department name query is supported. |
| limit | number (optional) Example: limit=100 Limit number on how many data will be returned. Limit can range between 1 and 100, with default number is 100. |
| offset | number (optional) Offset number on how many data will be skipped before returning the next data. Offset can range between 0 and total sites, with default number is 0. |
| x-api-key required | string Example: 4921f457d0277b412e13dc3e38df27e8 |
{- "message": "SUCCESS",
- "data": {
- "docs": [
- {
- "siteID": "aeacd1a9-89b6-4249-beda-eb52089df8e3",
- "siteName": "Sample Site",
- "timezone": "Asia/Jakarta",
- "address": "123 Main Street, Jakarta",
- "departments": [
- {
- "departmentID": "dept-123",
- "name": "Department A"
}
], - "createdAt": "2023-08-29T05:09:59.609Z",
- "updatedAt": "2023-08-29T05:09:59.609Z"
}
], - "limit": 100,
- "offset": 0,
- "totalDocs": 100,
- "totalPage": 1
}
}Returns a single site detail by its unique identifier.
| siteID required | string <uuid> Unique identifier of the site (UUID) |
| x-api-key required | string |
{- "message": "success",
- "data": {
- "siteID": "string",
- "name": "string",
- "organizationID": "string",
- "subtitle": "string",
- "country": "string",
- "province": "string",
- "city": "string",
- "address": "string",
- "locationName": "string",
- "coordinates": {
- "latitude": 0,
- "longitude": 0
}, - "primaryDepartment": "string",
- "departmentList": [
- "string"
], - "timezone": "string",
- "utcOffset": 0,
- "disabled": true,
- "isMultiSite": true,
- "photoURL": "string",
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}
}Returns a paginated list of active users. Optionally filter by name or email.
| search | string User name, partial name, or email |
| startDate required | string <date> Example: startDate=2026-05-01 |
| endDate required | string <date> Example: endDate=2026-05-31 |
| page | number Default: 1 |
| limit | number <= 100 Default: 10 |
| x-api-key required | string |
{- "message": "success",
- "data": {
- "docs": [
- {
- "userID": "string",
- "displayName": "string",
- "email": "string",
- "role": "string",
- "status": "active",
- "phoneNumber": "string",
- "language": "string",
- "authType": "string",
- "photoURL": "string",
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}
], - "totalDocs": 0,
- "limit": 0,
- "page": 0,
- "totalPages": 0
}
}Returns a single user detail by their unique identifier.
| userID required | string Unique identifier of the user |
| x-api-key required | string |
{- "message": "success",
- "data": {
- "userID": "string",
- "displayName": "string",
- "email": "string",
- "role": "string",
- "status": "active",
- "phoneNumber": "string",
- "language": "string",
- "authType": "string",
- "photoURL": "string",
- "isOnboarded": true,
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}
}Returns a paginated list of questionnaires. Optionally filter by title.
| search | string Questionnaire title or partial title |
| page | number Default: 1 |
| limit | number <= 100 Default: 10 |
| x-api-key required | string |
{- "message": "success",
- "data": {
- "docs": [
- {
- "questionnaireIndexID": "string",
- "title": "string",
- "latest": "string",
- "versions": [
- "string"
], - "questionCount": 0,
- "disabled": true,
- "createdAt": "2019-08-24T14:15:22Z",
- "updatedAt": "2019-08-24T14:15:22Z"
}
], - "totalDocs": 0,
- "limit": 0,
- "page": 0,
- "totalPages": 0
}
}Returns a paginated list of active schedules.
| page | number Default: 1 |
| limit | number <= 100 Default: 10 |
| x-api-key required | string |
{- "message": "success",
- "data": {
- "docs": [
- { }
], - "totalDocs": 0,
- "limit": 0,
- "page": 0,
- "totalPages": 0,
- "totalPercentage": 0,
- "isTruncated": true
}
}Returns a paginated list of departments. Optionally filter by name.
| search | string Department name or partial name |
| page | number Default: 1 |
| limit | number <= 100 Default: 10 |
| x-api-key required | string |
{- "message": "success",
- "data": {
- "docs": [
- {
- "departmentID": "string",
- "name": "string",
- "description": "string",
- "email": "string",
- "status": "active"
}
], - "totalDocs": 0,
- "limit": 0,
- "page": 0,
- "totalPages": 0
}
}