Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Welcome to Nightfall's Firewall for AI Developers Scan and Workflow APIs documentation. This documentation helps developers leverage Nightfall AI's industry-leading detection engine to identify and protect sensitive customer and corporate data anywhere. It prevents unauthorized access and data breaches and allows you to focus on innovation.
Scan prompts, text, documents, spreadsheets, logs, zips, JSON, images, etc., for PII, PHI, PCI, banking information, API keys, passwords, and network information with the highest accuracy and lightning-fast response times. Redact sensitive findings with customizable formatting.
Leverage the full potential of the Nightfall console application through our Workflow APIs. Customize your SIEM workflows and reporting, take actions, update support tickets, alert users, search violations, annotate findings, create reports, and more.
AI-Powered Identification: Utilize advanced AI models to detect and prevent security threats in real-time.
Comprehensive Sensitive Data Detection: Identify PII, PHI, PCI, banking information, API keys, passwords, and network information across various formats including text, documents, spreadsheets, logs, zips, and images.
Customizable Redaction: Tailor data protection to your needs with fully customizable redaction for each sensitive entity type.
Flexible Detectors: Leverage Nightfall’s comprehensive list of machine learning-based detectors, customize them, or create your own with specialized logic.
High Accuracy and Performance: Achieve precision and recall rates of 95% or higher, handle over 1K requests per second, and experience latency of less than 100 ms.
Seamless Integration: Easily integrate with your existing AI development and data engineering tools for smooth and efficient operation.
You can leverage Nightfall’s machine learning-based detectors or create your own detectors with customized logic to scan third-party apps, internal services, and data silos to identify instances of potentially sensitive types of data such as:
Personally Identifiable Information (PII) including Social Security Numbers, passport numbers, email addresses, or date of birth
Protected Health Information (PHI) such as insurance claim numbers or ICD10 codes
Financial information like credit card numbers or bank routing numbers
Secrets such as API and cryptographic Keys, database connection strings, passwords, etc.
Key features of Nightfall’s detection engine include:
Defining minimum confidence thresholds and minimum finding counts on detectors to reduce the chance of false positives.
Specifying and on detectors to fine-tune their accuracy to better suit your use cases.
Choosing which detectors are triggered for each policy.
The Nightfall API consumes arbitrary data as input either as or as and allows you to use any combination of detectors to return a collection of “findings" objects.
The detectors may be or defined as part of the .
The findings display the relevant detector, the likelihood of a match, and the location within the given data where the matched token occurred (not only in terms bytes — there is support for tabular and JSON data as well).
You can take protective action on sensitive text by , substituting, or encrypting it with the API. You may also set up to receive asynchronous notifications when findings are detected.
The Nightfall API is RESTful and uses JSON for its payloads. Our API is designed to have predictable, resource-oriented URLs for each endpoint and uses to indicate any API errors.
You may test out the API through the
The following guide will walk you through getting started and describe the API functionality in more detail. If you want to execute an API call immediately, see our guide to see how to obtain an API Key and make a simple scan request.
After that, you can learn about Nightfall with our Key Concepts section, which will also help you get set up with Nightfall.
If you’re looking for more ideas about best to leverage Nightfall’s functionality, see our guide.
We have created numerous that demonstrate how to implement DLP for a variety of platforms (including OpenAI, LangChang, Amazon, Datadog, and Elasticsearch) and handle various scenarios (such as detecting sensitive data in GenAI prompts or detecting PII on your machine in real-time).
We also have several language-specific to get you up and running in Java, Python, Go, Node.js, and Ruby.
You can also quickly test out Nightfall detectors or your custom Detection Rules in the . Please also consult our Detector to see the variety of built-in detectors that Nightfall offers.
The page allows you to create API keys and manage Detectors and Detection Rules through a straightforward user interface. Log in here to access the Dashboard, or sign up to create a free account.
For frequently asked questions, feedback, and other help, please contact Nightfall support at . We also host on Wednesdays at 12pm PT to help answer questions, talk through any ideas, and chat about data security. We would love to see you there!
Nightfall’s file scan API allows a user to upload a file in chunks, then to scan it with Detection Rules once the upload is complete.
The scan will then be processed asynchronously before sending the results to the webhook URL that is provided along with your Detection Rules.
The following sequence diagram illustrates the full process for scanning a binary file with Nightfall.
For a detailed walkthrough of the API calls necessary to upload and scan a file and full script that shows the entire process, see
In order to utilize the File Scanning API you need the following:
An active API Key authorized for file scanning passed via the header Authorization: Bearer <key>
Nightfall offers many useful features beyond its detectors, including:
The ability to use and to narrow the scope of matches.
The ability to create in a way that is highly configurable so that sensitive data is appropriately obfuscated.
The ability to create that determine how leaks of sensitive information should be mitigated (i.e. through alerts sent to email or Slack).
Network information such as IP Address or MAC Address
The Nightfall API uses API keys to authenticate requests. You can create and view your API keys in the Nightfall app on the Manage API Keys page.
Your API keys carry many privileges, so be sure to keep them secure. Do not share your secret API keys in publicly accessible areas such as GitHub, client-side code, or anywhere else that would compromise their secrecy. If you believe one of your API Keys has been compromised, you should delete it through the Dashboard.
All API requests must be made over HTTPS.
Calls made over plain HTTP will fail.
API requests without authentication will fail.
The Nightfall Developer Playground (playground.nightfall.ai) is a sample app that you may use to test out API functionality before writing any code.
Our playground environment allows you to:
Test Detectors and Detection Rules. Here are some sample datasets.
Generate sample data for DLP testing.
Explore a sample app built on our APIs
A Nightfall Detection Policy associated with a webhook URL
A web server configured to listen for file scanning results (detailed information to follow)
File scanning also support Nightfall's functionality for Using Exclusion Rules and Using Context Rules as part of your scan requests.

Firewall for AI provides a flexible and extensible API that allows you to scan a wide variety of data types, including plain text, structured and unstructured files, and even images. Our API can handle data in various formats such as JSON, XML, CSV, and more. Visit our detector glossary at help.nightfall.ai/docs/detector-glossary to explore the comprehensive list of supported data types and file formats
Firewall for AI is a powerful API that acts as a middleware layer or client wrapper to protect your AI models from consuming sensitive data. By integrating Firewall for AI into your application via API calls, you can proactively prevent data leaks and maintain compliance without disrupting your existing workflows or model updates.
Absolutely! In addition to the pre-built detectors, Firewall for AI allows you to create custom detectors tailored to your specific requirements. You can either fine-tune one of our pre-configured detection rules or build your own detector from scratch using our intuitive API. Nightfall supports many traditional detector types such as regular expressions, exact data matching, and word list/dictionaries. Check out our dedicated guide on creating custom detectors for more information.
The scan endpoint allows you to apply Policies and Detection Rules to a list of text strings provided as a payload.
You may use Pre-Configured Detection Rules or Create Inline Detection Rules
Text scanning supports the use of Exclusion Rules, Context Rules, and Redaction as well as other Scanning Features.
For scanning files, see Scanning Files.
Note that you must generate an API key to send requests to the Nightfall API.
curl --request POST \
--url https://api.nightfall.ai/v3/scan \
--header 'Accept: application/json' \
--header 'Authorization: Bearer NF-rEpLaCeM3w1ThYoUrNiGhTfAlLKeY123' \
--header 'Content-Type: application/json' \
--data '
{
"policy": {
"detectionRules": [
{
"detectors": [
{
"minNumFindings": 1,
"minConfidence": "LIKELY",
"displayName": "US Social Security Number",
"detectorType": "NIGHTFALL_DETECTOR",
"nightfallDetector": "US_SOCIAL_SECURITY_NUMBER"
}
],
"name": "My Match Rule",
"logicalOp": "ANY"
}
]
},
"payload": [
"The customer social security number is 458-02-6124",
"No PII in this string"
]
}Policies allow customers to create templates for their most common workflows by unifying a set of Detection Rules with the actions to be taken when those rules are triggered, including:
automated actions such as redaction of findings
alerting through webhooks
Once defined, a Policy may be used in requests to the Nightfall API, such as calls to scan file uploads, though automated redactions are not available for uploaded files at this time.
To create a policy:
Log in to Nightfall.
Click Policies under the Configuration section.
Click + New Policy.
Select Developer APIs.
Select the Detection Rules to be included in the policy and click Next.
Configure a notification channel. Click to learn more about alert channel configuration. If you wish to setup a webhook alert channel, click for details.
Click Next.
(Optional) Enable the Redact Message toggle switch. This is an automated action that is triggered when sensitive data is found. The action automatically redacts sensitive data.
Click Next.
Enter a name for the policy.
To configure Webhook as an alert channel:
Enable the Webhook Alert notification channel.
In the Configure Webhook URL field, enter the URL of the Webhook to which you wish to send notifications.
(Optional) Click Add Headers to add header key value pairs.
Click Validate.
Similarly, you can also use HTTP alerts channel.
Before you use the scan endpoint, there are a number of actions to do within the Nightfall dashboard to get your environment set up properly.
See Creating an API Key to see how to create the necessary Authentication token for making API calls.
See Creating a Detector for how to define your own custom logic for detecting sensitive data
See Creating Detection Rules for how to aggregate Detectors for use in the scan endpoint
See for how to set up common workflows that combine your Detection Rules with remediation actions such as alerting.
The following sample datasets can be used to test Nightfall's advanced AI-based detection capabilities.
This data has been fully de-identified and can be used to test any data loss prevention (DLP) platform.
The Nightfall API supports the ability to send asynchronous notifications when findings are detected as part of a scan request.
The supported destinations for these notifications include external platforms, such as Slack, email, or url to a SIEM log collector as well as to a webhook server.
Nightfall issues notifications under the following scenarios:
to notify a client about the results of a file scan request. File scans themselves are always performed asynchronously because of complexity relating to text extraction and data volume.
to notify a client about results from a text scan request. Although results are already delivered synchronously in the response object, clients may configure the request to forward results to other platforms such a webhook, SIEM endpoint, or email through a policy
To create a webhook you will need to and then set up a
For more information on how webhooks and asynchronous notifications are used please see our guides on:
In order to accept requests from Nightfall, a Webhook server must use a signing key to verify requests.
To access or generate your Webhook signing key, start by logging in to the Nightfall dashboard.
Select the Developer Platform > Manage API Keys using the navigation bar on the left side of the page. You will see the Webhook signing section:
Unlike the API Key, it is possible to reveal the signature via the "eye" icon furtherest to the left of the three icons displayed.
You may copy the current value to your clipboard with the "copy" icon in the center of the three icons displayed.
You may also regenerate the key with the circular arrow icon furthest to the right.
Use this value as shown in the code examples that are used in the following sections.
Firewall for AI DLP APIs enables developers to write custom code to sanitize data anywhere–RAG data sets, analytics data stores, data pipelines, and unsupported SaaS applications.
Using regex to identify long patterns in images can be challenging because OCR systems. In such cases, even Nightfall may not achieve 100% character-by-character accuracy. To improve results, you must introduce higher levels of flexibility into your regex patterns to accommodate common OCR inconsistencies. Here are some typical OCR challenges to keep in mind:
Spell-check noise: Spell-checking tools can add artifacts like red underlines, which may interfere with text recognition.
Character ambiguity:
Protected health information (PHI), also referred to as personal health information, describes a patient's medical history — including ailments, various treatments, and outcomes. PHI may include:
demographic information
test and laboratory results
mental health conditions
The API expects an API Key to be passed via the Authorization: Bearer <key> HTTP header.
To create and manage API keys:
Log in to Nightfall.
Click Overview under the DEVELOPER APIS section.
While using Nightfall's Scan API, you may encounter some of the common errors outlined below. Try following the provided troubleshooting steps.
If problems persist, please for further assistance.
The following error codes are returned as part of a standard HTTP response.
Here are real-world scenarios where the Nightfall MCP server delivers immediate value:
Example: "Show me all active high-risk violations from GitHub in the last week"
The AI automatically uses search_violations with appropriate filters and returns results in seconds. You can then ask follow-up questions like "Which repository has the most violations?" or "Show me the sensitive data found in violation abc-123" without manually constructing queries.
Example: "What has user been doing in the last 30 days?"
Get a complete timeline of user activity including file downloads, permission changes, and policy violations. The AI summarizes patterns and flags anomalies automatically.
Example: "Resolve all pending Slack violations from the #general channel"
Instead of manually processing violations one by one, describe the action in natural language. The AI finds matching violations and executes the appropriate remediation action.
The native SaaS app APIs can be utilized by customers using Nightfall’s SaaS apps, supported natively, to fetch violations, search violations by app meta-data attributes, and fetch findings within violations. These DLP APIs do not provide access to violations for apps scanned via the developer platform. These APIs require you to create an API key as outlined in the . However, to use these APIs, you need not create any detectors, detection rules, and policies in the developer platform.
If you are using Nightfall SaaS apps, you can use APIs to fetch violations, search through the violations, and fetch specific findings within the Violations. To scan data in any custom apps or cloud infrastructure services like AWS S3, you must use the APIs in the section.
The Nightfall MCP (Model Context Protocol) server enables AI assistants like Claude, ChatGPT, and Cursor to interact directly with your Nightfall security data. Instead of navigating dashboards or running API queries manually, you can use natural language to investigate violations, search for exfiltration events, review security posture, and take remediation actions.
Key Benefits
Natural Language Interface: Ask questions in plain English instead of learning complex query syntax
Faster Investigations: Get instant answers to security questions without switching between tools
If you encounter issues not covered in this guide:
Email Support:
We continuously improve the MCP server based on customer feedback. Please share:
Feature requests for new query capabilities
Use cases we should highlight in documentation
We offer a free tier that allows you to sign up and start using Firewall for AI with zero upfront costs or commitments. This tier provides a generous data scanning capacity and access to all the core features.
We offer enterprise pricing plans for advanced requirements such as higher data volumes, custom rate limits, and dedicated support.
Contact our team at sales@nightfall.ai or via the contact form on our website to discuss your specific needs and get a tailored pricing quote.
Nightfall provides you the flexibility to easily integrate into applications using programming languages. The supported languages are as follows.
You can use the posture management APIs to search posture events, fetch posture events and also event details. Additionally, you can also view details of the user (actor) whose actions triggered an event, and details of the asset that triggered an event.
APIs to monitor and manager integrations
Yes, you can test out the detection engine, including 70+ pre-built detectors without writing any code or having to sign up in our .
Leverage our software development kits (SDKs) to enable easier, faster, and more stable engagement with the Nightfall APIs. Nightfall has a growing library of language specific SDKs including for:
Workflow Integration: Access Nightfall data directly in your development and collaboration environments
Automated Analysis: Let AI help you identify patterns, summarize findings, and recommend actions
If there is a language-specific SDK that you would find valuable but is not here, please don't hesitate to reach out to product@nightfall.ai.
(Optional) Enter a Description for the policy and click Next.
Verify the configurations and click Submit.
Once validated, you can click Next to proceed.

Firewall for AI offers a rich set of pre-built detectors that can identify many different types of sensitive data, including personally identifiable information (PII), payment card industry data (PCI), protected health information (PHI), secrets, and credentials. These detectors are powered by advanced machine learning models and can be easily integrated into your application with just a few lines of code. Refer to our detector glossary at https://help.nightfall.ai/detection_platform/detection_glossary for a complete list of available detectors.
In two ways:
Nightfall’s out of the box detectors can be modified with context rules and exclusion rules.
Nightfall also supports inputting custom regular expressions or word lists (i.e. dictionaries) as detectors in the RE2 standard as documented here.
At Nightfall, data security and privacy are our top priorities. We have implemented stringent security measures to protect your sensitive data at every stage of the scanning process. All data transmitted to our API is encrypted in transit using industry-standard protocols. We adhere to best practices for secure coding, undergo regular security audits, and maintain compliance with relevant security standards. Visit our security and compliance page at nightfall.ai/security for more details on our commitment to data protection.
Don't hesitate to get in touch with us directly via email at support@nightfall.ai or through the contact form on our website.
We host Nightfall Developer Office Hours on Wednesdays at 12 pm PT to help answer questions, talk through any ideas, and chat about data security. We would love to see you there!
You can schedule a demo or a meeting with our sales/solutions engineering team directly via Calendly here. If you don't see a suitable time, please email us at sales@nightfall.ai.
For support inquiries, please email us at support@nightfall.ai.
For sales inquiries, please email us at sales@nightfall.ai.

Getting Started
Learn how to create a Nightfall API key, Detectors, Detection rules, and Polices
Nightfall APIs
Nightfall Scan and Workflow APIs enable you to integrate DLP protection programatically
SDKs
Learn how to leverage the Nightfall Software Development Kits (SDKs)
Language Specific Guides
Learn how to use Nightfall's APIs/SDKs with specific programming languages.
Integration Tutorials
Learn how to integrate Nightfall into some GenAI apps and datastores.
Popular Use Cases
Review popular scenarios and apply them to your DLP use case.
Detection Playground
A code free environment for test driving Firewall for AI.







This error most often occurs when there is something syntactically incorrect in the body of your request. Check your request format and try again. For example, this error could occur if the request body size is greater than 500 KB, or if the number of items to scan in the payload exceeds 50,000.
401
Unauthorized
You may be using an incorrect API key or calling the wrong endpoint.
422
Unprocessable Entity
You may be using an invalid or unrecognized detector set. You may also have exceeded the maximum allowable payload size; try spreading your payload across multiple requests.
429
Too Many Requests or Quota Exceeded
Either your monthly request limit has been exceeded, or you have exceeded the allowed rate limit. Consider upgrading to a higher volume plan, or wait several moments to retry the requests.
500
Internal Server Error
Wait a few moments and try again. If the problem persists, Nightfall may be experiencing an outage.
400
Bad Request
The AI retrieves relevant data, performs grouping and aggregation, and creates a formatted report—all from a single request.
Example: "Are there any exfiltration events involving bulk downloads from Google Drive?"
Quickly identify potential data theft attempts by searching for specific event patterns across your cloud storage integrations.
Example: "List all posture events with permission changes this month"
Monitor access control changes across your environment to identify security configuration drift or policy violations.
Integration challenges or configuration pain points
Success stories of how MCP improves your security operations
Model Context Protocol Specification: https://modelcontextprotocol.io
Nightfall API Documentation: https://help.nightfall.ai/developer-api
Webinars: https://www.nightfall.ai/webinars
The character l (lowercase L) may be read as the digit 1.
The letter B may appear as the digit 8.
Underscore handling: An underscore (_) is sometimes interpreted as a space, particularly when spell-check artifacts are present.
Line wrapping: OCR may introduce unexpected newlines when text wraps across multiple lines.
Periods and punctuation: Spell-check artifacts or font issues may result in extraneous periods (.) or other punctuation being added to the output. En dash (–) and hyphens (-) may be interchanged.
For reference, OCR tools like Tesseract typically achieve 85-98% character accuracy for similar input, and our system operates within a similar range. Given this, tuning your regex to be more forgiving (e.g., allowing for optional characters or slight variations) can significantly improve detection rates.
Example Regex (original and loosened)
original: ATATT3xFfGF0[A-Za-z0-9=_\-]*[=A-Za-z0-9]{9}
loosened: ATATT[A-Za-z0-9_\-– @.\n=]*[A-Za-z0-9_\- @.\n]{7,11}
shortened the literal match prefix
excluded the the literal zero (0) from the prefix
added period (.) and newline () chars
relaxed the char length
insurance information
The Health Insurance Portability and Accountability Act (HIPAA) of 1996 is the primary law that oversees the use of, access to, and disclosure of PHI in the United States. HIPAA lists 18 different personal information identifiers (PII) that, when paired with health information, become PHI. In order to more accurately detect potential PHI, Nightfall has introduced specific new detectors that allow for specialized combinations.
These HIPAA PII and PHI-specific detectors intelligently aggregate Nightfall's built-in detector to ensure compliance with governing law. For example, finding a patient's name in a document or message is not considered HIPAA PII as it does not uniquely identify an individual, many people can share the same name. However, the information would be considered HIPAA PII if the patient's name and address were in the same message.
Specific PHI and HIPAA PII can be detected with greater confidence, especially as they relate to specific medical codes or terms in association with specific logical combinations of other PII. For instance when the patient's name and date of birth or a person's name and street address or any of a set of particular PII (phone number email, SSN, etc) it would be considered HIPAA PII.
If the combined detectors all match with a confidence of "Very Likely" it would match our "HIPAA PII Very Likely" Detection Rule. Otherwise if these detectors match with a confidence of "Likely" it would match our "HIPAA PII Likely" Detection Rule.
Alternatively when any of the above PII options are found in conjunction with a specific set of medical related codes or terms (IDC Codes, FDA Drug Names or Codes, Procedures), that finding could be flagged as PHI.
When all the detectors within these PHI Detection Rules make findings that have a confidence of "Very Likely," that would match our "PHI Very Likely" Detection Rule, while if some are all are met with a confidence of "Likely" that would match our "PHI Likely" Detection Rule.
Our PHI Detectors may be used just like other Detectors with Policies or Inline Detection Rules.
Click Create key.
The Generate API Key window is displayed.
Enter a name for the API key and click Create.
The API key is generated and displayed. Click the copy button to copy the API key and store it in a. secure location. Once you click the Got it button, you cannot retrieve the API key again.
🚧Be Sure to Record the API Key's Value
For security reasons, after closing the window, you will not be able to recover the key's value.
Once you close the window, the Your API Keys section will display your newly generated key, with the majority of the Key redacted.
You can click the Create Key button to create new keys (assuming your license allows you to generate additional keys). You can click the Delete icon against an API key to delete the key.
This section describes the terms you will need to know when using the API.
Detectors provide the logic to find potentially sensitive pieces of data.
When this logic detects such data, the Detector is considered "triggered."
Nightfall's has numerous pre-built Detectors that are trained via machine learning. Detectors may also be defined with regular expressions or dictionaries. Their accuracy may be further refined with exclusion rules and context rules. Whether a Detector is triggered may be controlled by a minimum confidence threshold per Detector and minimum number of findings per Detector as set on a Detection Rule.
The built-in set of Detectors cover a number of different categories of data, including:
Standard PII (e.g. social security number, driver's license number, ID card image)
PCI (Credit Card Number, credit card image)
Healthcare (e.g. PHI, US Medicare Beneficiary Number)
Finance - Banking (e.g. SWIFT code, IBAN code, US bank routing number)
Network (e.g. an IP Address)
The full set is enumerated in the .
Nightfall also supports and word lists for any custom detectors that you may want to implement.
Over time, we've aggregated the following , which you're welcome to select from to save you some time. Please note that a regular expression is an established yet limited method that searches for pre-defined patterns, so your mileage may vary.
You can test regular expressions .
You can input custom detectors in two ways: directly in the Nightfall by navigating to Detectors → New Detector → Regular expression, or
An exclusion rule is a regular expression or word list that will be used once a Detector is triggered by its primary expression or word list to eliminate false positives.
For instance, you may have a Detector designed to detect phone numbers. However, you may have a particular set of phone numbers that you use for testing purposes that are known not to be valid (e.g. they start with the prefix 555) and this should be ignored. Adding an exclusion rule would allow you to prevent those matches from being returned by the API.
See:
Context Rules are additional matching expressions for a Detector that may be used to adjust the confidence score of a match.
You may provide a regular expression and the number of leading or trailing characters within which a match of that expression must occur in order to adjust the confidence level to a particular level.
For instance, if you found a sequence that appeared to be a social security number based on its length or formatting, you might boost the confidence score if it was preceded by the text like “SSN” or “Social Security Number.”
You may request that a sequence of bytes of a given length be provided from before and after the text that triggers a Detection Rule.
This information can help you better understand whether or not something is an actual violation by observing the circumstances within which the detected text was found.
You are limited to a maximum of 40 bytes of this context text preceding and trailing the match for a total of 80 bytes overall.
See:
Detection Rules are aggregations of Detectors that are assigned a minimum confidence level. The identifiers of Detection Rules are used as a parameter to the API.
You may create Detection Rules as described in the section and use their identifier as part of API calls to scan content.
Alternatively you may specify Detection Rules in each API call, as described in the scan method documentation below.
A Detection Rule is composed of a list of Detectors with which you wish to scan each request payload, where any or all Detectors may be satisfied in order to trigger the rule. You can add up to 50 total Detectors with a limit of 30 regular expression type custom detectors.
Additionally, each Detector in the Detection Rule is assigned a “minimum confidence” level (see and a minimum number of findings to determine if the Detection Rule should be considered triggered.
Detection results will be returned with one of the following confidence values.
In practice, the API will only return detections assigned a POSSIBLE or higher confidence level.
VERY_LIKELY (recommended)
LIKELY
POSSIBLE
UNLIKELY
Learn more about what different confidence levels mean and how to choose the right minimum confidence level for your detection rule .
Policies allow you to create templates for the most common workflows by unifying a set of Detection Rules with the actions to be taken when those rules are triggered, including:
automated actions such as redaction of findings
alerting through webhooks
Once defined, a Policy may be used in requests to the Nightfall API, such as calls to scan file uploads, though automated redactions are not available for uploaded files at this time.
File scans of Microsoft Office, Apache parquet, csv, and tab separated files will provide additional properties to locate findings within the document beyond the standard byteRange, codepointRange, and lineRange properties.
Findings will contain a columnRange and a rowRange that will allow you to identify the specific row and column within the tabular data wherein the finding is present.
This functionality is applicable to the following mime types:
text/csv
text/tab-separated-values
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
application/vnd.ms-excel
data files are also accepted.
Below is a sample match of a spreadsheet containing dummy PII where a SSN was detected in the 2nd column and 55th row.
Nightfall provides special handling for archives of GitHub repositories.
Nightfall will scan the repository history to discover findings in particular checkin, returning the hash for the checkin.
In order to scan the repository, you will need to create a clone, i.e.
git clone https://github.com/nightfallai/nightfall-go-sdk.git
This creates a clone of the Nightfall go SDK.
You will then need to create an archive that can be uploaded using Nightfall's file scanning sequence.
zip -r directory.zip directory
Note that in order to work, the hidden directory .github must be included in the archive.
When you initiate the with this file, you will receive scan results that contain the commitHash property filled in.
Using the Nightfall go SDK archive created above, a simple example would be to scan for URLs (i.e. strings starting with http:// or https://), which will send results such as the following:
To retrieve the specific checkout, you will need to clone the repository, i.e.
git clone https://github.com/nightfallai/nightfall-go-sdk.git
You can then checkout the specific commit using the commit hash returned by Nightfall.
Note that you are in a when working with this sort of check out of a repository.
These examples demonstrate the flexibility of natural language queries. You don't need to memorize syntax - just describe what you need.
"Show me today's violations"
"List high-risk violations in the last 7 days"
"Find violations in the engineering-team Slack channel"
"What GitHub repositories have violations?"
"Show violations by "
"What files has accessed this week?"
"Track user activity for "
"Find all Salesforce violations in the Sales org"
"Show Google Drive files shared externally"
"List Confluence pages with public links"
"Check Microsoft Teams for sensitive data sharing"
"Compare violation trends month over month"
"Identify users with the most violations"
"What types of sensitive data are most commonly exposed?"
"Summarize security posture improvements over the last quarter"
"Mark these violations as resolved"
"Block access to this file"
"Delete violations in test channels"
"Quarantine all high-risk violations from last month"
Connection Issues
Problem: "Unauthorized" or 401 errors
Solutions:
Verify your API key is correctly pasted in the configuration file (no extra spaces)
Check that the API key hasn't expired or been revoked in the Nightfall dashboard
Ensure you're using "Bearer YOUR_KEY" format, not just "YOUR_KEY"
Restart your AI client after updating the configuration
Problem: MCP server not appearing in client
Solutions:
Verify the configuration file is in the correct location for your operating system
Check JSON syntax is valid (use a JSON validator if needed)
For Claude Desktop: ensure npx is installed (requires Node.js)
Review client logs for specific error messages
Problem: No results returned
Solutions:
Broaden your time range (data may be older than expected)
Check filter criteria aren't too restrictive
Verify the integration or resource name is spelled correctly
Confirm you have violations/events matching your criteria in the Nightfall dashboard
Problem: Rate limit errors (429)
Solutions:
Wait for the duration specified in the Retry-After header
Reduce query frequency or batch similar requests
Contact Nightfall support if hitting limits during normal usage
Problem: Slow query responses
Solutions:
Use more specific filters to reduce result set size
Limit date ranges to recent periods when possible
Request paginated results for large datasets
Complex aggregations may take longer—this is expected behavior
This section consists of use case tutorials for various scenarios of Firewall for AI. The tutorials explained in this section are as follows.
Learn how to set up a server to handle results of file scans and alerts sent based on policy alert configurations.
Nightfall will send a POST request with a JSON payload with a single field challenge containing randomly-generated bytes when it sends a message to a user-provided webhook address. This is to ensure that the caller owns the server.
In order to authenticate your webhook server to Nightfall, you must reply with (1) a 200 HTTP Status Code, and (2) a plaintext request body containing only the value of the challenge key.
If Nightfall receives the expected value back, then the file scan operation will proceed; otherwise it will be aborted.
When a server responds successfully to a challenge request, the validity of that URL will be cached for up to 24 hours, after which it will need to be validated again.
If the webhook cannot be reached, you will receive an error with the code "40012" and the description "Webhook URL validation failed" when you initiate the scan.
Nightfall supports Detectors that will scan for file names, file types, and file finger prints.
In addition to scanning the content of files, you may configure the Detectors to scan file names as well.
This is done through the “scope” attribute of a Detector.
The scope attribute allows you to scan either within file contents, the file name, or both the file contents and file name.
File extensions can be scanned for by creating a Regular Expression type custom Detector with a scope to scan only file names ("File") or both the content and file name ("ContentAndFile"), as shown in the example request below.
In addition to scanning based on file name, you may also use a which allows you to scan for files based on their mime-type.
Note that confidence sensitivity does not apply to file names. Sensitive findings will always be reported on.
Nightfall’s File Type detection allows you to implement compliance policies that detect and alert you when particular file types that are not allowed in a given location are discovered.
As part of submitting a file scan request, the request payload must contain a reference to a URL defined as part of a policy defined inline.
When Nightfall prepares a file scan operation, it will issue a challenge to the to verify its legitimacy.
After the file scan has been processed asynchronously, the results will be delivered to the webhook.
For a file scan, your webhook will receive a request body that will be a JSON payload containing:
the upload UUID (uploadID)
An Exclusion Rule allows you to refine a Detector to make sure false positives are not surfaced by Nightfall.
For instance you may want to detect whether credit card numbers are being shared inappropriately in your organization. However, there may be cases where members of your QA are sharing test credit card numbers, which should not be considered a violation and should be ignored by Nightfall.
In the following example, we define a Detector with a regular expression to match credit cards.
We then add an exclusion for some known test credit cards.
As the resulting payload shows, only the 3rd provided Credit Card number matches because the first two items in the payload are included in our ExclusionRules word list.
Leaked secrets, such as credentials needed to authenticate and authorize a cloud provider’s API request, expose company software, services, infrastructure, and data to hackers.
Nightfall has developed technology to detect secrets and label findings to speed SecOPs workflows from being clogged and eliminate false positive alerts.
Nightfall uses machine learning models trained on a large (millions of lines of code) diverse dataset (including all programming languages and application types) to ensure best-in-class secret detection accuracy and coverage.
For a growing set of the most popular services, Nightfall will:
label detected secrets by vendor and service type (returned the kind field of the response)
You can use the surrounding context of a match to help determine how likely it is that your potential match should actually be considered as a match by adjusting its confidence rating.
You can also tell the Detection Rule to return a portion of the surrounding context for manual review.
In the following example, in addition to providing a regular expression to match Social Security Numbers, we also look to see if someone has written the text “SSN” before and after the match, which might be a label indicating it is indeed a social security number. In which case, we change our confidence score to “VERY_LIKELY.” We then provide two possible matches in our payload, the first of which contains the string “SSN”.
In the results, you can see the confidence for the first finding in the payload has been set to VERY_LIKELY while the second item is only LIKELY.
To prevent misuse and ensure the stability of our platform, we enforce a rate limit on an API Key and endpoint basis, similar to the way many other APIs enforce rate limits.
When operating under our Free plan, accounts and their corresponding API Keys have a rate limit of 5 requests per second on average, with support for bursts of 15 requests per second. If you upgrade to a paid plan – the Enterprise plan – this rate increases to a limit of 10 requests per second on average and bursts of 50 requests per second.





Sensitive Data in GitHub Repositories
If the finding in a GitHub repository is considered to be sensitive, it should be considered compromised and appropriate mitigation steps (i.e. secrets should be rotated).
curl --location --request POST 'https://api.nightfall.ai/v3/scan' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer NF-rEpLaCeM3w1ThYoUrNiGhTfAlLKeY123' \
--header 'Content-Type: application/json' \
--data-raw '{
"policy": {
"detectionRules": [
{
"detectors": [
{
"regex": {
"pattern": "(?:(4[0-9]{12}(?:[0-9]{3})?)|(5[1-5][0-9]{14})|(6(?:011|5[0-9]{2})[0-9]{12})|(3[47][0-9]{13})|(3(?:0[0-5]|[68][0-9])[0-9]{11})|((?:2131|1800|35[0-9]{3})[0-9]{11}))",
"isCaseSensitive": false
},
"exclusionRules": [
{
"wordList": {
"values": [
"4111111111111111",
"5105105105105100"
]
},
"exclusionType": "WORD_LIST",
"matchType": "FULL"
}
],
"minNumFindings": 1,
"minConfidence": "POSSIBLE",
"displayName": "Credit Card Reg Ex",
"detectorType": "REGEX"
}
],
"name": "Credit Card Detection Rule",
"logicalOp": "ALL"
}
]
},
"payload": [
"5105105105105100",
"4111111111111111",
"4012888888881881"
]
}'curl --location --request POST 'https://api.nightfall.ai/v3/scan' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer NF-rEpLaCeM3w1ThYoUrNiGhTfAlLKeY123' \
--header 'Content-Type: application/json' \
--data-raw '{
"policy": {
"detectionRules": [
{
"detectors": [
{
"regex": {
"isCaseSensitive": false,
"pattern": "\\d{3}-\\d{2}-\\d{4}"
},
"contextRules": [
{
"regex": {
"pattern": "SSN",
"isCaseSensitive": false
},
"proximity": {
"windowBefore": 20,
"windowAfter": 20
},
"confidenceAdjustment": {
"fixedConfidence": "VERY_LIKELY"
}
}
],
"minNumFindings": 1,
"minConfidence": "POSSIBLE",
"detectorType": "REGEX",
"displayName": "SSN Match Detector"
}
],
"name": "SSN Match Detection Rule",
"logicalOp": "ALL"
}
],
"contextBytes": 20
},
"payload": [
"My SSN is 555-55-5555",
"Here it is : 555-55-5555"
]
}
'a boolean indicating whether or not any data in the file matched the provided detection rules (findingsPresent)
a pre-signed S3 URL where the caller may fetch the findings for the scan (findingsURL). if there are no findings in the file, this field will be empty.
the date until which the findingsURL is valid (validUntil) formatted to RFC 3339. Results are valid for 24 hours after scan completion. The time will be in UTC.
the value you supplied for requestMetadata. Callers may opt to use this to help identify their input file upon receiving a webhook response. Maximum length 10 KB.
Below is an example of a payload sent to the webhook URL.
If you follow the URL (before it expires) it will return a JSON representation of the findings similar to those returned by the Scan Plain Text endpoint.
In this example, we have uploaded a zip file with a python script (upload.py) and a README.md file. A Detector in our DetectionRule checks for the presence of the string http://localhost
{
"findings":[
{
"path":"Sheet1 (5)",
"detector":{
"id":"e30d9a87-f6c7-46b9-a8f4-16547901e069",
"name":"US social security number (SSN)",
"version":1
},
"finding":"624-84-9182",
"confidence":"LIKELY",
"location":{
"byteRange":{
"start":2505,
"end":2516
},
"codepointRange":{
"start":2452,
"end":2463
},
"lineRange":{
"start":55,
"end":55
},
"rowRange":{
"start":55,
"end":55
},
"columnRange":{
"start":2,
"end":2
},
"commitHash":""
},
"matchedDetectionRuleUUIDs":[
"950833c9-8608-4c66-8a3a-0734eac11157"
],
"matchedDetectionRules":[
]
},
...{
"findings":[
{
"path":"f607a067..53e59684/nightfall.go",
"detector":{
"id":"6123060e-2d9f-4f35-a7a1-743379ea5616",
"name":"URL"
},
"finding":"https://api.nightfall.ai/\"",
"confidence":"LIKELY",
"location":{
"byteRange":{
"start":142,
"end":168
},
"codepointRange":{
"start":142,
"end":168
},
"lineRange":{
"start":16,
"end":16
},
"rowRange":{
"start":0,
"end":0
},
"columnRange":{
"start":0,
"end":0
},
"commitHash":"53e59684d9778ceb0f0ed6a4b949c464c24d35ce"
},
"beforeContext":"tp\"\n\t\"os\"\n\t\"time\"\n)\n\nconst (\n\tAPIURL = \"",
"afterContext":"\n\n\tDefaultFileUploadConcurrency = 1\n\tDef",
"matchedDetectionRuleUUIDs":[
"cda0367f-aa75-4d6a-904f-0311209b3383"
],
"matchedDetectionRules":[
]
},
...cd nightfall-go-sdk
git checkout 53e59684d9778ceb0f0ed6a4b949c464c24d35ce{
"findings":[
[
],
[
],
[
{
"finding":"4012888888881881",
"detector":{
"name":"Credit Card Reg Ex",
"uuid":"93024e88-e6de-4c84-8295-75157cdd1b52"
},
"confidence":"LIKELY",
"location":{
"byteRange":{
"start":0,
"end":16
},
"codepointRange":{
"start":0,
"end":16
},
"rowRange":null,
"columnRange":null,
"commitHash":""
},
"matchedDetectionRuleUUIDs":[
],
"matchedDetectionRules":[
"Credit Card Detection Rule"
]
}
]
],
"redactedPayload":[
"",
"",
""
]
}{
"findings":[
[
{
"finding":"555-55-5555",
"beforeContext":"My SSN is ",
"detector":{
"name":"SSN Match Detector",
"uuid":"6131f41c-dbdd-47a9-8c6f-1819c9baf388"
},
"confidence":"VERY_LIKELY",
"location":{
"byteRange":{
"start":10,
"end":21
},
"codepointRange":{
"start":10,
"end":21
},
"rowRange":null,
"columnRange":null,
"commitHash":""
},
"matchedDetectionRuleUUIDs":[
],
"matchedDetectionRules":[
"SSN Match Detection Rule"
]
}
],
[
{
"finding":"555-55-5555",
"beforeContext":"Here it is : ",
"detector":{
"name":"SSN Match Detector",
"uuid":"6131f41c-dbdd-47a9-8c6f-1819c9baf388"
},
"confidence":"LIKELY",
"location":{
"byteRange":{
"start":13,
"end":24
},
"codepointRange":{
"start":13,
"end":24
},
"rowRange":null,
"columnRange":null,
"commitHash":""
},
"matchedDetectionRuleUUIDs":[
],
"matchedDetectionRules":[
"SSN Match Detection Rule"
]
}
]
],
"redactedPayload":[
"",
""
]
}{
"findingsURL": "https://files.nightfall.ai/asdfasdf-asdf-asdf-asdf-asdfasdfasdf.json?Expires=1635135397&Signature=asdfasdfQ2qTmPFnS9uD5I3QGEqHY2KlsYv4S-WOeEEROj~~x6W2slP2GvPPgPlYs~lwdr-mtJjVFu4LtyDhdfYezC7B0ysfJytyMIyAFriVMqOGsRJXqoQfsg8Ckd2b6kRcyDZXJE25cW8zBS08lyVwMBCsGS0BKSin8uSuD7pQu3QAubT7p~MPkfc6PSXYIJREBr3q4-8c7UnrYOAiXfSW1AmFE47rr3Wxh2TpU3E-Fxu-6e3DKN4q6meACdgZb2KHZo3e-NK7ug9f8sxBp1YT0n5oiVuW4KXguIyXWN~aKEHMa6DzZ4cUJ61LmnMzGndc2sVKhii39FHwTsYog__&Key-Pair-Id=asdfOPZ1EKX0YC",
"validUntil": "2021-10-25T04:16:37.734633129Z",
"uploadID": "152848af-2ac9-4e0a-8563-2b82343d964a",
"findingsPresent": true,
"requestMetadata": "",
"errors": []
}{
"findings":[
{
"path":"fileupload/upload.py",
"detector":{
"id":"58861dee-b213-4dbc-97fa-a148acb8bd1a",
"name":"localhost url"
},
"finding":"http://localhost",
"confidence":"LIKELY",
"location":{
"byteRange":{
"start":105,
"end":121
},
"codepointRange":{
"start":105,
"end":121
},
"lineRange":{
"start":7,
"end":7
}
},
"beforeContext":"PLOAD_URL = getenv(\"FILE_UPLOAD_HOST\", \"",
"afterContext":":8080/v3\")\nNF_API_KEY = getenv(\"NF_API_K",
"matchedDetectionRuleUUIDs":[
"950833c9-8608-4c66-8a3a-0734eac11157"
],
"matchedDetectionRules":[
]
},
{
"path":"fileupload/README.md",
"detector":{
"id":"58861dee-b213-4dbc-97fa-a148acb8bd1a",
"name":"localhost url"
},
"finding":"http://localhost",
"confidence":"LIKELY",
"location":{
"byteRange":{
"start":570,
"end":586
},
"codepointRange":{
"start":570,
"end":586
},
"lineRange":{
"start":22,
"end":22
}
},
"beforeContext":"t the script will send the requests to `",
"afterContext":":8080`, but this can be overridden using",
"matchedDetectionRuleUUIDs":[
"950833c9-8608-4c66-8a3a-0734eac11157"
],
"matchedDetectionRules":[
]
},
{
"path":"fileupload/README.md",
"detector":{
"id":"58861dee-b213-4dbc-97fa-a148acb8bd1a",
"name":"localhost url"
},
"finding":"http://localhost",
"confidence":"LIKELY",
"location":{
"byteRange":{
"start":965,
"end":981
},
"codepointRange":{
"start":965,
"end":981
},
"lineRange":{
"start":26,
"end":26
}
},
"beforeContext":"ice deployment you want to connect to | ",
"afterContext":":8080 |\n| `NF_API_KEY` | the API Ke",
"matchedDetectionRuleUUIDs":[
"950833c9-8608-4c66-8a3a-0734eac11157"
],
"matchedDetectionRules":[
]
}
]
}When a customer signs up for the developer platform, Nightfall automatically generates a unique siging secret for them.
This secret is used to sign requests to the customer's configured webhook URL.
If you has any concerns that their signing secret may have leaked, you can request rotation at any time by reaching out to Nightfall Customer Success.
For security purposes, the webhook includes a signature header containing an HMAC-SHA256 digital signature that customers may use to authenticate the client.
In order to authenticate requests to the webhook URL, customers may use the following algorithm:
Check for the presence of the headers X-Nightfall-Signature and X-Nightfall-Timestamp. If these headers are not both present, discard the request.
Read the entire request body into a string body.
Verify that the value in the X-Nightfall-Timestamp header (the POSIX time in seconds) occurred recently. This is to protect against replay attacks, so a threshold on the order of magnitude of minutes should be reasonable. If a request occurred too far in the past, it should be discarded.
Concatenate the timestamp and body with a colon delimiter, i.e. timestamp:body.
Compute the HMAC SHA-256 hash of the payload from the previous step, using your unique signing secret as the key. Encode this computed value in hex.
Compare the value of the X-Nightfall-Signature header to the value computed in the previous step. If the values match, authentication is successful, and processing should proceed. Otherwise, the request must be discarded.
The snippet below shows how you might implement this authentication validation in Python:
An example implementation of a simple webhook server is below.
You can test your webhook with a tool such as ngrok which allows you expose a web server running on your local machine to the internet.
In the above example, the webhook server is running on port 8075. To route ngrok requests to this server, once you run the python script (having installed the necessary dependencies such getenv and Flask), you would run ngrok as follow:
./ngrok http 8075
See the section on Alerting for details about the json payloads for the different messages sent to webhook servers.
{"challenge": "z78woE1uDFu7tPrPvEBV"}from datetime import datetime, timedelta
import hmac
import hashlib
from flask import request
SIGNING_SECRET = "super-secret"
given_signature = request.headers.get('X-Nightfall-Signature')
req_timestamp = request.headers.get('X-Nightfall-Timestamp')
now = datetime.now()
if now-timedelta(minutes=5) <= datetime.fromtimestamp(int(req_timestamp)) <= now:
raise Exception("could not validate timestamp is within the last few minutes")
computed_signature = hmac.new(
SIGNING_SECRET.encode(),
msg=F"{req_timestamp}:{request.get_data(as_text=True)}".encode(),
digestmod=hashlib.sha256
).hexdigest().lower()
if computed_signature != given_signature:
raise Exception("could not validate signature of inbound request!")import hmac
import hashlib
from os import getenv, path, mkdir
from flask import Flask, request
import requests
app = Flask(__name__)
output_dir = "findings"
SIGNING_SECRET = getenv("NF_SIGNING_SECRET")
@app.route("/", methods=['POST'])
def hello():
content = request.get_json(silent=True)
challenge = content.get("challenge")
if challenge:
return challenge
else:
verify_signature()
print(F"Received request metadata: {content['requestMetadata']}")
print(F"Received errors: {content['errors']}")
if not content["findingsPresent"]:
print(F"No findings for {content['uploadID']}")
return "", 200
print(F"S3 findings valid until {content['validUntil']}")
response = requests.get(content["findingsURL"])
save_findings(content["uploadID"], response.text)
return "", 200
def verify_signature():
if SIGNING_SECRET is None:
return
given_signature = request.headers.get('X-Nightfall-Signature')
nonce = request.headers.get('X-Nightfall-Timestamp')
computed_signature = hmac.new(
SIGNING_SECRET.encode(),
msg=F"{nonce}:{request.get_data(as_text=True)}".encode(),
digestmod=hashlib.sha256
).hexdigest().lower()
if computed_signature != given_signature:
raise Exception("could not validate signature of inbound request!")
def save_findings(scan_id, finding_json):
if not path.isdir(output_dir):
mkdir(output_dir)
output_path = path.join(output_dir, f"{scan_id}.json")
with open(output_path, "w+") as out_file:
out_file.write(finding_json)
print(F"Findings for {scan_id} written to {output_path}")
if __name__ == "__main__":
app.run(port=8075)The signing secret should never be stored in plaintext, as a leak compromises the authenticity of webhook requests.
This functionality is implemented by creating a specific Detector called a “File Type Detector”
To create a File Type Detector, select “Detectors” from the left hand navigation and click the button labeled “+New Detector” in the upper right hand corner. From there a drop down list of Detector types will be displayed which will include the “File Type” Detector type.
You will then select one or more file types for which to scan by selecting from a list of mime-types
You can either scroll through the list of mime-types in the select box or you may type in a portion of the mime-type and the contents of the select box will be filtered to match your input.
Nightfall supports detection for a wide variety of mime-types. See the Internet Assigned Numbers Authority’s (IANA) website for a definitive list of mime-types. Note however that Nightfall does not support the detection of audio and video related mime-types.
Detection of file types is done based on the file contents, not its extension. However, you can create Detectors that scan file names by setting the scope attribute.
File Type Detectors vary from other Nightfall Detectors in that the attributes of scope and confidence are not relevant to File Type Detectors
Once you have added all the mime-types you wish to scan for, save your new Detector. You may then add your new Detector to and Policies.
Nightfall allows you to discover the location of specific files that you have deemed sensitive and want to avoid sharing.
This discovery is done through document fingerprinting. Fingerprinting is the process of algorithmically creating a unique identifier for a file by mapping the data of the document to a signature that can be recalled quickly. This allows the file to be identified in a manner akin to how human fingerprints uniquely identify individual people.
This functionality is achieved in Nightfall by creating a specific Detector type called a File Fingerprint Detector.
The Fingerprint Detector allows you to create a fingerprint for one more files (a sort “handful” of fingerprints, if you would).
To create a Fingerprint Detector, select “Detectors” from the left hand navigation and click the button labeled “+New Detector” in the upper right hand corner. From there a drop down list of Detector types will be displayed which will include the “Fingerprint” Detector type.
When you create a File Fingerprint Detector you can upload up to 50 files that need to be fingerprinted. The file size limit is 25MB.
Once the fingerprint is generated, the actual content of the file is discarded so no sensitive content is stored on Nightfall’s system.
These Detectors may only be created through the console.
You may then treat the Fingerprint detector like any other and incorporate it into a using its unique Detector identifier.
You may incorporate these Detectors into Policies that will alert you whenever files that match the fingerprint are detected.
curl --request POST \
--url https://api.nightfall.ai/v3/upload/<fileid>/scan \
--header 'Accept: application/json' \
--header 'Authorization: Bearer NF-<yourNightfallKey> \
--header 'Content-Type: application/json' \
--data '
{
"policy": {
"detectionRules": [
{
"detectors": [
{
"regex": {
"pattern": "*\.txt",
"isCaseSensitive": false
},
"detectorType": "REGEX",
"scope": "ContentAndFile"
}
],
"name": "File Name Detector",
"logicalOp": "ANY"
}
]
}
}
You can not update Fingerprint Detectors, so any modification to the original file or underlying requires that you create a brand new Fingerprint Detector.
label detected secrets as active risks by validating supported credential types with their associated service endpoints (returned as the status of the service)
Our current solution supports the following vendors covering a diverse set of use cases, including cloud storage/infrastructure, communication, social networks, software development, banking, observability, and payment processing.
This list is not static and will continue to grow as we add support for detecting API keys from additional services. If you want to detect API keys from a service not listed below, please contact us.
AWS
Azure
Confluence
Confluent
GitLab
JIRA
JWT
Nightfall
Salesforce
Sendgrid
Slack
Snyk
Below is an example of how an AWS Key would be shown in a finding.
The following values are returned for the status field:
ACTIVE
EXPIRED
UNVERIFIED
This value will be based on what information is returned by the corresponding service when attempting the validate the key. If no data is returned fro the service, it will be considered UNVERIFIED.
To use this functionality, you use our existing built-in API_KEY detector to scan a data source such as Git Repository. Below is an example using a detection rule defined in line for a text scan.
{
"finding": "zImaKNJJ8u/seIbm1UszokVz3SSARukJs6cghEBXD",
"detector": {
"name": "API key",
"uuid": "0e95732f-bc5c-448f-9d15-bd1417177360"
},
"confidence": "VERY_LIKELY",
...
"findingMetadata": {
"apiKeyMetadata": {
"status": "ACTIVE",
"kind": "AWS",
"description": "Access Key ID: AKIA52FSMBPZS1JIDTPX"
}
}
}
curl --request POST \
--url https://api.nightfall.ai/v3/scan \
--header 'Authorization: Bearer NF-rEpLaCeM3w1ThYoUrNiGhTfAlLKeY123' \
--header 'Content-Type: application/json' \
--data '{
"policy": {
"detectionRules": [
{
"detectors": [
{
"detectorType": "NIGHTFALL_DETECTOR",
"nightfallDetector": "API_KEY",
"minNumFindings": 1,
"minConfidence": "LIKELY",
"displayName": "API Key"
}
],
"name": "My Match Rule",
"logicalOp": "ANY"
}
]
},
"payload": [
"Is this an active nightfall key? NF-OZ6F9fzF2z5mRxMrUdfL8FddFS51kPzE"
]
}'5
15
Enterprise
10
50
The Nightfall API follows standard practices and conventions to signal when these rate limits have been exceeded.
Successful requests return a header X-Rate-Limit-Remaining with the integer number of requests remaining before errors will be returned to the client.
When your application exceeds the rate limit for a given API endpoint, the Nightfall API will return an HTTP response code of 429 "Too Many Requests.” If your use case requires increased rate limiting, please reach out to support@nightfall.ai.
Additionally, these unsuccessful requests return the number of seconds to wait before retrying the request in a Retry-After Header.
Your Request Rate Limiting throttles how frequently you can make requests to the API. You can monitor your rate limit usage via the `X-Rate-Limit-Remaining` header, which tells you how many remaining requests you can make within the next second before being throttled.
Your Quota limits how many requests you can make within a given period. Your current remaining quota and the end of your current quota period are denoted by the following response headers.
X-Quota-Remaining
string
The requests remaining in your quota for this period. Will be reset to the amount specified in your billing plan at the end of your quota cycle.
X-Quota-Period-End
For the free plan, we allow 5 requests per second and 10000 requests in a day.
Free
Say you have a number of files containing customer or patient data and you are not sure which of them are ok to share in a less secure manner. By leveraging Nightfall’s API you can easily verify whether a file contains sensitive PII, PHI, or PCI.
To make a request to the Nightfall API you will need:
A Nightfall API key
A list of data types you wish to scan for
Data to scan. Note that the API interprets data as plaintext, so you may pass it in any structured or unstructured format.
You can read more about or about our in the linked reference guides.
To run the following API call, we will be using Python's standard json, os, and requests libraries.
First we define the endpoint we want to reach with our API call.
Next we define the headers of our API request. In this example, we have our API key set via an environment variable called "NIGHTFALL_API_KEY". Your API key should never be hard-coded directly into your script.
Next we define the detectors with which we wish to scan our data. The detectors must be formatted as a list of key-value pairs of format {‘name’:’DETECTOR_NAME’}.
Next, we build the request body, which contains the detectors from above, as well as the raw data that you wish to scan. In this example, we will read it from a file called sample_data.csv.
Here we assume that the file is under the 500 KB payload limit of the Scan API. If your file is larger than the limit, consider breaking it down into smaller pieces across multiple API requests.
Now we are ready to call the Nightfall API to check if there is any sensitive data in our file. If there are no sensitive findings in our file, the response will be "[[]]".
[[]]
Endpoint
https://api.nightfall.ai/mcp
Protocol
MCP Streamable HTTP (JSON-RPC 2.0)
Before connecting to the Nightfall MCP server, ensure you have:
An active Nightfall subscription with appropriate permissions
A Nightfall API key from the Developer Platform
An MCP-compatible AI client (Claude Desktop, Cursor, Windsurf, or custom)
Log in to the Nightfall Dashboard at
Navigate to Developer Platform > API Keys
Click Generate New Key and provide a descriptive name (e.g., "Claude MCP Integration")
Copy the generated key immediately - it will only be shown once
⚠️ Security Note: Your API key provides full access to your Nightfall data. Never commit it to version control or share it publicly.
The Nightfall MCP server supports any MCP-compatible client. Below are configuration examples for popular AI tools.
Add the following configuration to your Claude Desktop config file:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
json
Replace YOUR_NIGHTFALL_API_KEY with your actual API key, then restart Claude Desktop.
Open Cursor Settings > MCP and add:
json
Add to ~/.codeium/windsurf/mcp_config.json:
json
For custom MCP clients, connect using Streamable HTTP transport:
The server operates in stateless mode and returns application/json responses.
The Firewall for AI Platform differs from other solutions like Google DLP and Amazon Macie, as well as open source solutions like truffleHog, on a number of dimensions summarised below.
Accuracy
While solutions like Google DLP have a broad set of detectors, many of them are rules or regex based, which means many of the detectors are not usable in practice. Likewise, detection has been found to be inconsistent in some cases, perhaps due to internal A/B testing.
Because of the limitations of regex-based rules, instead of leveraging machine learning based detectors, OSS detection solutions tend to have a much higher rate of false positives compared to Nightfall.
Detector configurability and ability to provide metrics at the token level makes Nightfall accurate and actionable to engineering & security teams.
Convenience
Want to leave the last 4 digits of a credit card number visible, securely encrypt emails, and completely remove SSNs from your data? The Nightfall platform allows you to redact/replace, substitute, and/or encrypt sensitive data findings in the same API call as your inspection request.
Ease of use
All inspection configuration in Google DLP is done as code, which makes it challenging to easily update, visualize, and modify detection rules and configuration. Nightfall allows for configuration as code, as well as the Nightfall for creating and updating detection rules, which makes it easier to collaborate.
OSS secret detection tools tend to rely heavily on manual creation of regex-based detection compared to an ability to programmatically scan text and file inputs using 150+ detectors in Nightfall – e.g. truffleHog only enables you to scan for secrets like passwords and private keys whereas Nightfall scans for not only secrets and credentials, but also allows you to use our vast detector library to scan for PII, PCI, and PHI.
File parsing
To parse files with Google DLP and Macie, each requires that they be in their respective cloud storage (Google Cloud Storage or S3, respectively). With the Nightfall Developer Platform, we take care of storage requirements for you. Uploaded assets are stored encrypted at rest with minimal access permissions, and are automatically deleted after 24 hours.
Amazon’s file parsers are limited to around 20 file types. Most notably, Macie does not support images. Text extraction via machine-learning based OCR for images is a core component of Nightfall’s file scanning endpoint.
Open source secrets detection solutions are limited in their detection capabilities. Namely, these projects do not support scanning binary files. Nightfall supports binary files and the ability to scan diff files.
Platform agnostic
Each cloud provider's DLP products are geared towards protecting their own cloud services. For example, Google DLP’s native integrations are limited to Google Cloud offerings such as BigQuery. Similarly, Macie is primarily designed around scanning AWS S3 buckets. The interface is largely geared towards exploring sensitive data across S3 buckets. To scan content outside of S3, Amazon’s recommendation is to move or replicate the data into S3 to scan, which is impractical.
OSS solutions are primarily designed around git repositories.
Nightfall has native integrations with many cloud applications like Slack, Atlassian, GitHub, Google Drive, as well a broad set of tutorials and open source code so you can build integrations into any data silo with ease. For example, this includes services like Snowflake, Airtable, and more.
Support and documentation
Google DLP and Macie are loosely supported products and with many cloud offerings, support is hard to come by. Nightfall is laser-focused on best-of-breed content inspection and we are ready to address your questions and use cases.
Nightfall also has extensive documentation including SDKs for multiple languages including Python, Java, NodeJS, and Go - with more under consistent development.
Cost and scale
Costs can balloon quickly with commercial services. They also have rate limits that don’t suit high data volumes.
Open source solutions have high hidden costs in the form of TCO, maintenance, and opportunity cost.
Nightfall offers a custom enterprise tier that can help you scale pricing based on your anticipated usage as well as custom rate limits.
In this example, we'll walk through making a request to the scan endpoint.
The endpoint inspects the data you provide via the request body and reports any detected occurrences of the sensitive data types you are searching for.
Please refer to the API reference of the scan endpoint for more detailed information on the request and response schemas.
In this sample request, we provide two main fields:
a policy and its detection rules that we want to use when scanning the text payload
a list of text strings to scan
Nightfall has the ability to send alerts when a violation is detected.
Policies for alerting may be configured through the Nightfall app user interface or they may be set up . Policies that are configured under Developer Platform > Overview > Policies may be used in the API by referencing their Policy UUID.
The way that an alert notification presents itself depends on the platform in question.
For example, notifications sent to Slack will appear as formatted messages sent by the Nightfall Alerts Bot. Other destinations such as email, SIEM url, and webhooks, will present the information as JSON objects.
In the case of webhooks, detailed information about the finding will be sent. For other destinations, sensitive information is redacted.
In order to use asynchronous notifications with Slack, you must install the Nightfall Alerts plugin from the Slack Marketplace.
See our end user documentation on installing for more details.
Once you have authenticated Nightfall to your Slack workspace, you can provide any public
This guide describes how to use Nightfall with the Java programming language.
The example below will demonstrate how to use Nightfall’s text scanning functionality to verify whether a string contains sensitive PII using the Nightfall Java SDK.
In this tutorial, we will be downloading, setting up, and using the Java SDK provided by Nightfall.
To make a request to the Nightfall API you will need:
A Nightfall API key
Datadog
ElasticSearch
GCP
Google API
GitHub
Notion
Okta
Paypal
Plaid
Postmark
Postman
RapidAPI
Splunk
Square
Stripe
Twilio
Zapier
datetime
The date and time at which your quota will be reset, encoded as a string in the RFS-3339 format.




detector_list = ['US_SOCIAL_SECURITY_NUMBER', 'ICD9_CODE', 'US_DRIVERS_LICENSE_NUMBER']
detector_object = [{'name':detector} for detector in detector_list][{'name':'US_SOCIAL_SECURITY_NUMBER'},
{'name':'ICD9_CODE'},
{'name':'US_DRIVERS_LICENSE_NUMBER'}]Store the key securely (password manager recommended)
Authentication
Bearer token (Nightfall API key)
Available Tools
16 integrated security operations tools
import json
import os
import requestsendpoint = 'https://api.nightfall.ai/v1/scan'h = {
'Content-Type': 'application/json',
'x-api-key': os.getenv('NIGHTFALL_API_KEY')
}with open('sample_data.csv', 'r') as f:
raw_data = f.read()
d = {
'detectors': detector_object,
'payload':{'items':[raw_data]}
}import os
if os.stat('sample_data.csv').st_size < 500000:
print('This file will fit in a single API call.')
else:
print('This file will need to be broken into pieces across multiple calls.')response = requests.post(endpoint, headers = h, data = json.dumps(d))
if (response.status_code == 200) & (len(response.content.decode()) > 4):
print('This file contains sensitive data.')
print(json.loads(response.content.decode()))
elif response.status_code == 200:
print('No sensitive data detected. Hooray!')
else:
print(f'Something went wrong -- Response {response.status_code}.')[
[
{'fragment': '172-32-1176',
'detector': 'US_SOCIAL_SECURITY_NUMBER',
'confidence': {'bucket': 'LIKELY'},
'location': {'byteRange': {'start': 122, 'end': 133},
'unicodeRange': {'start': 122, 'end': 133}}},
{'fragment': '514-14-8905',
'detector': 'US_SOCIAL_SECURITY_NUMBER',
'confidence': {'bucket': 'LIKELY'},
'location': {'byteRange': {'start': 269, 'end': 280},
'unicodeRange': {'start': 269, 'end': 280}}},
{'fragment': '213-46-8915',
'detector': 'US_SOCIAL_SECURITY_NUMBER',
'confidence': {'bucket': 'LIKELY'},
'location': {'byteRange': {'start': 418, 'end': 429},
'unicodeRange': {'start': 418, 'end': 429}}}
]
]{
"mcpServers": {
"nightfall": {
"command": "npx",
"args": [
"-y",
"mcp-remote@latest",
"https://api.nightfall.ai/mcp",
"--header",
"Authorization: Bearer YOUR_NIGHTFALL_API_KEY"
]
}
}
}{
"mcpServers": {
"nightfall": {
"url": "https://api.nightfall.ai/mcp",
"headers": {
"Authorization": "Bearer YOUR_NIGHTFALL_API_KEY"
}
}
}
}{
"mcpServers": {
"nightfall": {
"serverUrl": "https://api.nightfall.ai/mcp",
"headers": {
"Authorization": "Bearer YOUR_NIGHTFALL_API_KEY"
}
}
}
}POST https://api.nightfall.ai/mcp
Authorization: Bearer YOUR_NIGHTFALL_API_KEY
Content-Type: application/jsonThe aggregate length of all strings in payload list must not exceed 500 KB, and the number of items in the payload may not exceed 50,000.
Alternatively you may define your policy in code by using a built in Nightfall detector from the as follows:
See for more information about how policies and detection rules may be defined through code.
Executing the curl request will yield a response as follows.
The API call returns a list, where the item at each index is a sublist of matches for the provided detector types.
The indices of the response list correspond directly to the indices of the list provided in the request payload.
In this example, the first item in the response list contains a finding because one credit card number was detected in the first string we provided. The second item in the response list is an empty list because there is no sensitive data in the second input string we provided. The third item in the returned list contains multiple findings as a result of multiple Detectors within the Detection Rule being triggered.
You can read further about the fields in the response object in the .
To send notifications to a private channel, a member of the channel should invite the Nightfall bot to the specific private channel and allow channel access to the bot.
Follow the steps below to invite Nightfall Alerts bot to a private channel:
Go to the Slack channel in question
Type /invite @Nightfall Alerts as a message
Press 'Enter' (you should see a message that Nightfall Alerts has now joined the channel)
If any findings are detected as part of that request, then the Nightfall Alerts bot will send a message to the channel you configured. Conversely, if there are no findings in the request payload, then Nightfall will not send an alert message.
Documentation TBD
Email is unauthenticated, so you can get started using Nightfall to send email alerts without any initial setup work.
Nightfall will send an email to the provided address only if findings were detected as part of the request. The findings themselves will be attached in a JSON file.
You may send your alerts to a designated url, such as an endpoint hosted by SIEM software for log collection.
In addition to the url, you may provide headers, either for security or logging purposes.
See in our end user guide or our for more details.
You may use a webhook server to programmatically handle a finding, allowing you to create your own custom workflows with your own or 3rd party systems.
Nightfall will always send an alert to the client's webhook server if it is provided as part of an API request, even if the scan request yielded no findings.
See for more details.
The request body sent by Nightfall is JSON, and uses the schemas in the section documented below.
Since file scans can produce a large number of results, findings are not transmitted directly in the notification that Nightfall sends. The notification object looks like the following:
The requestMetadata field contains arbitrary contents provided by the client at request time, and can be used by the client to correlate this response to the original request.
The value of the findingsURL field is a pre-signed URL, which means anyone with the link can download the file. Therefore, this URL itself should be treated as sensitive and must not be leaked. The object stored at this URL is a JSON file containing a single key findings containing a list of all data detected from the request. The schema for the finding object inside the list is shared between the text-based and file-based API endpoints.
The payload that is forwarded on behalf of text scanning requests is identical to the response body that is synchronously returned to the client. Refer to the for more details on this payload.
You can read more about obtaining or about our available from the linked reference guides.
You can add the Nightfall package to your project by adding a dependency to your pom.xml:
First add the required imports to the top of the file.
These are the objects we will use from the Nightfall SDK, as well as some collection classes for data handling.
We can then declare some data to scan in a List:
Create a ScanTextRequest to scan the payload with. First create a new instance of the credit card detector, and set to trigger if there are any findings that are confidence LIKELY or above.
Add a second detector, looking for social security numbers. Set it to be triggered if there is at least a possible finding.
Combine these detectors into a detection rule, which will return findings if either of these detectors are triggered.
Finally, combine the payload and configuration together as a new ScanTextRequest, and return it.
Use the ScanTextRequest instance with a NightfallClient to send your request to Nightfall.
The resulting ScanTextResponse may be used to print out the results:
And that's it 🎉
You are now ready to use the Java SDK for other scenarios.
//Sample Payload
List<String> payload = Arrays.asList(
"hello",
"world",
"my data is 4242-4242-4242-4242 but shhhh 🙊 ",
"my ssn is 678-99-8212"
);curl --request POST \
--url https://api.nightfall.ai/v3/scan \
--header 'Accept: application/json' \
--header 'Authorization: Bearer NF-rEpLaCeM3w1ThYoUrNiGhTfAlLKeY123' \
--header 'Content-Type: application/json' \
--data '
{
"policy": {
"detectionRuleUUIDs": [
"950833c9-8608-4c66-8a3a-0734eac11157"
]
},
"payload": [
"4916-6734-7572-5015 is my credit card number",
"This string does not have any sensitive data",
"my api key is yr+ZWwIZp6ifFgaHV8410b2BxbRt5QiAj1EZx1qj and my 💳 credit card number 💰 is 30204861594838"
]
}
'curl --request POST \
--url https://api.nightfall.ai/v3/scan \
--header 'accept: application/json' \
--header 'Authorization: Bearer NF-rEpLaCeM3w1ThYoUrNiGhTfAlLKeY123' \
--header 'content-type: application/json' \
--data '
{
"policy": {
"detectionRules": [
{
"detectors": [
{
"nightfallDetector": "CREDIT_CARD_NUMBER",
"detectorType": "NIGHTFALL_DETECTOR",
"minConfidence": "POSSIBLE",
"minNumFindings": 1
}
],
"logicalOp": "ALL"
}
]
},
"payload": [
"4916-6734-7572-5015 is my credit card number",
"This string does not have any sensitive data",
"my api key is yr+ZWwIZp6ifFgaHV8410b2BxbRt5QiAj1EZx1qj and my 💳 credit card number 💰 is 30204861594838"
]
}
'{
"findings": [
[
{
"finding": "4916-6734-7572-5015",
"detector": {
"name": "Credit card number",
"uuid": "74c1815e-c0c3-4df5-8b1e-6cf98864a454"
},
"confidence": "VERY_LIKELY",
"location": {
"byteRange": {
"start": 0,
"end": 19
},
"codepointRange": {
"start": 0,
"end": 19
}
},
"matchedDetectionRuleUUIDs": [
"950833c9-8608-4c66-8a3a-0734eac11157"
],
"matchedDetectionRules": []
}
],
[],
[
{
"finding": "30204861594838",
"detector": {
"name": "Phone number",
"uuid": "d08edfc4-b5e2-420a-a5fe-3693fb6276c4"
},
"confidence": "LIKELY",
"location": {
"byteRange": {
"start": 94,
"end": 108
},
"codepointRange": {
"start": 88,
"end": 102
}
},
"matchedDetectionRuleUUIDs": [
"950833c9-8608-4c66-8a3a-0734eac11157"
],
"matchedDetectionRules": []
},
{
"finding": "30204861594838",
"detector": {
"name": "Credit card number",
"uuid": "74c1815e-c0c3-4df5-8b1e-6cf98864a454"
},
"confidence": "LIKELY",
"location": {
"byteRange": {
"start": 94,
"end": 108
},
"codepointRange": {
"start": 88,
"end": 102
}
},
"matchedDetectionRuleUUIDs": [
"950833c9-8608-4c66-8a3a-0734eac11157"
],
"matchedDetectionRules": []
}
]
]
}
"location": {
"byteRange": {
"start": 94,
"end": 108
},
"codepointRange": {
"start": 88,
"end": 102
}
},
"matchedDetectionRuleUUIDs": [
"950833c9-8608-4c66-8a3a-0734eac11157"
],
"matchedDetectionRules": []
},
{
"finding": "30204861594838",
"detector": {
"name": "Credit card number",
"uuid": "74c1815e-c0c3-4df5-8b1e-6cf98864a454"
},
"confidence": "LIKELY",
"location": {
"byteRange": {
"start": 94,
"end": 108
},
"codepointRange": {
"start": 88,
"end": 102
}
},
"matchedDetectionRuleUUIDs": [
"950833c9-8608-4c66-8a3a-0734eac11157"
],
"matchedDetectionRules": []
}
]
]{
"errors": [],
"findingsPresent": true,
"findingsURL": "https://files.nightfall.ai/877442c5-1573-4637-a223-595bf620e3e5.json?Expires=1645722381&Signature=C-kQbtonFAPXfooGcm0dYgbsn9jfGu~vGSv5yK5j1z2f7aAhk0WuaL4bISUwx5MZkQmPVFgeyMwemvEoI8aI11lPA-ORsX5LtRdGJBOma4sPVl~9f9qBPKE2VSrdGDmT4EpBLc8ewUtKrLm2xE-0BzW~5PdLSvZ~NQxtB7OMBaYm7h~y2NSUZfpqzdzENyKhyHx5QxH2PJvxeN5IvMXqNUrKyZsxviSYY6kDNAiGExS-u6PmKKS1GhXOaFLdJSRjgtFhUxDLyWl~xTYR-lJol5UTgtcuYU8AaJ3xVTF1-1JYRlioRlaf9shAvme4djFyg8k~zOB8bYgzBeaRqSjeWA__&Key-Pair-Id=K3RYMP51FKX5HX",
"requestMetadata": "some data",
"uploadID": "877442c5-1573-4637-a223-595bf620e3e5",
"validUntil": "2022-02-24T17:06:21.412377682Z"
}{
"findings": [
{
"detector": {
"id": "74d1315e-c0c3-4ef5-8b1e-6cf98664a854"
},
"finding": "4242-4242-4242-4242",
"confidence": "VERY_LIKELY",
"location": {
"byteRange": {
"start": 146,
"end": 165
},
"codepointRange": {
"start": 146,
"end": 165
},
"lineRange": {
"start": 3,
"end": 3
},
"rowRange": null,
"columnRange": null,
"commitHash": ""
},
"beforeContext": "nd HIPAA Defined PII\nHIPAA HIPAA hooray\n",
"afterContext": " is my credit card number\n\n",
"matchedDetectionRuleUUIDs": ["7bd6166a-b9af-4069-847d-487a88788122"],
"matchedDetectionRules": []
}
]
}{
"findings": [
[
{
"finding": "4242-4242-4242-4242",
"beforeContext": "hello world cc ",
"detector": {
"name": "Credit card number",
"uuid": "74c1815e-c0c3-4df5-8b1e-6cf98864a454"
},
"confidence": "VERY_LIKELY",
"location": {
"byteRange": {
"start": 15,
"end": 34
},
"codepointRange": {
"start": 15,
"end": 34
},
"rowRange": null,
"columnRange": null,
"commitHash": ""
},
"matchedDetectionRuleUUIDs": [
"42efe36c-6479-412a-9049-fd8cdf895ced"
],
"matchedDetectionRules": []
}
]
],
"redactedPayload": [""]
}<!--pom.xml-->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.foo</groupId>
<artifactId>my-artifact</artifactId>
<version>1.0.0</version>
<name>${project.groupId}:${project.artifactId}</name>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>ai.nightfall</groupId>
<artifactId>scan-api</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
</project>//List of imports
import ai.nightfall.scan.NightfallClient;
import ai.nightfall.scan.model.Confidence;
import ai.nightfall.scan.model.DetectionRule;
import ai.nightfall.scan.model.Detector;
import ai.nightfall.scan.model.LogicalOp;
import ai.nightfall.scan.model.NightfallAPIException;
import ai.nightfall.scan.model.ScanTextConfig;
import ai.nightfall.scan.model.ScanTextRequest;
import ai.nightfall.scan.model.ScanTextResponse;
import java.util.Arrays;
import java.util.List;//Build the Scan Request
public static ScanTextRequest buildScanTextRequest() {
// Define some detectors to use to scan your data
Detector creditCard = new Detector("CREDIT_CARD_NUMBER");
creditCard.setMinConfidence(Confidence.LIKELY);
creditCard.setMinNumFindings(1);
Detector ssn = new Detector("US_SOCIAL_SECURITY_NUMBER");
ssn.setMinConfidence(Confidence.POSSIBLE);
ssn.setMinNumFindings(1);
DetectionRule rule = new DetectionRule(Arrays.asList(creditCard, ssn), LogicalOp.ANY);
ScanTextConfig config = ScanTextConfig.fromDetectionRules(Arrays.asList(rule), 20);
return new ScanTextRequest(payload, config);
}//Run the Scan Request
public class Runner {
public static void main(String[] args) {
try (NightfallClient c = NightfallClient.Builder.defaultClient()) {
try {
ScanTextResponse response = c.scanText(buildScanTextRequest());
System.out.println("response: " + response.getFindings());
} catch (NightfallAPIException e) {
// not a checked exception, just for illustrative purposes
System.out.println("got error: " + e);
}
}
}
}The Document will guide you in making your first API request.
This page will get you up and running with the Nightfall API so you can start scanning for sensitive data.
The Nightfall API requires a valid API key to authenticate your API requests.
You can create API keys in the Dashboard.
Learn more about Authentication and Security.
Below is an example request to the scan endpoint.
To run this example yourself, replace the API key (NF-rEpLaCe...) with the one you created in the dashboard or set it as the environment variable NIGHTFALL_API_KEY as necessary.
The cURL example may be run from the command line without any additional installation. To run the Python example, you will need to download the corresponding SDK.
The Policy (policy) you define indicates what to scan for in your payload with a logical grouped (ANY or ALL) set of Detection Rules (detectionRules).
Detection Rules can be defined two ways:
, as shown above
in the Nightall app, which you will then .
Learn more about in the Nightfall app to create your own Detectors, Detection Rules, and Policies. See for an example as to how to execute queries using an existing Detection Rules UUID.
In the example above, two of Nightfall's native Detectors are being used: US_SOCIAL_SECURITY_NUMBER and CREDIT_CARD_NUMBER.
You can find a full list of native Detectors in the .
If you don't want to create your Detectors, Detection Rules, and Policies in the Nightfall app, but would prefer to do it in code, it is possible to define with your own regular expressions or word list as well as extend our native Detectors with and rules.
When defining a Detection Rule, you configure the minimum(minConfidence) and minimum number of times the match must be found (minNumFindings) for the rule to be triggered.
Another feature Nightfall offers is the ability to sensitive findings. Detectors may be configured (via redactionConfig) to replace the text that triggered them with a variety of customizable masks, including an encrypted version of the text.
In the payload body, you can see that we are submitting a list of three different strings to scan (payload). The first will trigger the U.S. Social Security Detector. The last will trigger the credit card Detector. The middle example will trigger neither.
The Nightfall API returns a response with an array (findings) with a length that corresponds to the length of the payload array. In this example, only the first and last items in the request payload triggered the Detectors, so the second element of the array is empty.
In the first element of the array, you can see details about which Detection Rule was triggered and the data that was found (finding). The response also provides a confidence level (confidence), as well as the location within the original text where the data was found either in terms of bytes (byteRange) or characters (codepointRange).
Congratulations! You have successfully completed the Nightfall Quickstart.
You can modify the Detectors or payload in the example request to get more practice with the Nightfall API.
The following workflows represent best practices for common security tasks. These step-by-step patterns guide you through effective multi-tool investigations.
Purpose: Conduct an end-to-end security incident investigation
Steps:
Identify the scope: Search for related events using search_violations, search_exfiltration_events, or search_posture_events with your search criteria
Gather details: For each relevant result, use get_violation, get_exfiltration_event, or get_posture_event to get full context including affected assets, actors, and risk levels
Review findings: For violations, use get_violation_findings to see exactly what sensitive data was detected
Check activity timeline: Use the appropriate activity tools to understand what remediation has already been attempted
Assess user behavior: If an actor is identified, use get_actor_activity to check their recent activity across all event types
Summarize and recommend: Provide a structured incident summary with scope, affected assets, actors involved, risk assessment, and specific remediation actions
Example Conversation:
"Investigate the incident involving repository finance-api"
"Show me the findings for violation abc-123"
"What has user jane@example.com been doing recently?"
"Summarize the risk and recommend next steps"
Purpose: Prioritize and triage active DLP violations for remediation
Steps:
Fetch active violations: Use search_violations with query state:ACTIVE sorted by RISK_DESC to get highest-risk violations first
Categorize by severity: Group violations by risk_label (CRITICAL, HIGH, MEDIUM, LOW) and integration
Example Conversation:
"Triage all active violations, prioritize by risk"
"Show me details for the top 5 high-risk violations"
"What are the findings for these violations?"
"Create a remediation plan for the critical violations"
Purpose: Generate security compliance summary across time periods
Steps:
Gather violation statistics: Use list_violations with createdAfter timestamp for your reporting period
Gather exfiltration statistics: Use list_exfiltration_events with the same time range
Gather posture statistics: Use list_posture_events
Example Conversation:
"Generate a compliance report for the last 90 days"
"Break down violations by integration and severity"
"Show me the top 10 incidents with details"
"What trends are emerging in our security posture?"
Purpose: Assess security risk profile for a specific user
Steps:
Find violations: Use search_violations with query user_email:[email] to find all DLP violations
Find exfiltration events: Use search_exfiltration_events with query actor_email:[email]
Find posture events
Example Conversation:
"Assess the risk profile for user john@company.com"
"Show me all violations and events involving this user"
"What patterns emerge from their behavior?"
"Recommend appropriate actions based on their risk level"
Purpose: Execute remediation actions on specific violations
Steps:
Review violation details: Use get_violation to understand context and available actions
Check findings: Use get_violation_findings to see what data is at risk
Verify appropriate action: Confirm the remediation action matches the violation severity and context
Example Conversation:
"Show me details for violation xyz-789"
"What are the available remediation actions?"
"Resolve this violation and document the action"
"Confirm the remediation was successful"
"Search for GitHub violations, get details on the top 3, and show me the sensitive findings"
"Find all violations by jane@company.com, check her recent activity, and assess her risk profile"
"List exfiltration events from last week, get details on any involving bulk downloads, and summarize the risk"
"Search for high-risk Slack violations, review their findings, and recommend remediation actions"
The most effective investigations use multiple tools in sequence. Follow these patterns:
Basic Investigation Pattern:
Search → Get Details → Analyze → Recommend
Deep Investigation Pattern:
Search → Get Details → Get Findings → Check Activity → Assess Actor → Recommend
Remediation Pattern:
Search → Get Details → Verify Context → Take Action → Confirm
When asking complex questions, the AI will automatically chain tools in the optimal order. You can also explicitly request multi-step workflows: "Search for high-risk violations, review the top 5, and create a remediation plan."
Be specific about time ranges: "last 7 days" is clearer than "recently"
Use exact usernames or email addresses when investigating specific actors
Ask follow-up questions to drill deeper: "Show me the findings" after reviewing a violation
Request summaries for complex data: "Summarize these violations by severity"
Store API keys in secure credential managers, never in code or configuration files committed to version control
Rotate API keys quarterly or immediately if compromise is suspected
Use dedicated API keys for each integration rather than sharing across systems
Review API key permissions regularly and follow least-privilege principles
Be specific about time ranges: "last 7 days" is clearer than "recently"
Use exact usernames or email addresses when investigating specific actors
Ask follow-up questions to drill deeper: "Show me the findings" after reviewing a violation
Request summaries for complex data: "Summarize these violations by severity"
Set up dedicated Slack/Teams channels for security alerts and use MCP to investigate directly from your collaboration tool
Create saved prompts for common investigations to maintain consistency across your security team
Document investigation procedures that leverage MCP for faster onboarding of new analysts
Use MCP in conjunction with the Nightfall console for comprehensive security operations
This guide describes how to use Nightfall with the Python programming language.
The example below will demonstrate how to use Nightfall’s text scanning functionality to verify whether a string contains sensitive PII using the Nightfall Python SDK.
To request the Nightfall API you will need:
A Nightfall API key
An existing Nightfall Detection Rule
Data to scan. Note that the API interprets data as plaintext, so you may pass it in any structured or unstructured format.
You can read more about or about our in the linked reference guides.
In this tutorial, we will be downloading, setting up, and using the Python SDK provided by Nightfall.
We recommend you first set up a virtual environment. You can learn more about that .
You can download the Nightfall SDK from PyPi like this:
We will be using the built-in os library to help run this sample API script. This will be used to help extract the API Key from the OS as an environment variable.
Next, we extract our API Key, and abstract a nightfall class from the SDK, for it. In this example, we have our API key set via an environment variable called NIGHTFALL_API_KEY. Your API key should never be hard-coded directly into your script.
Next we define the Detection Rule with which we wish to scan our data. The Detection Rule can be and referenced by UUID.
In this example, we will use some example data in the payload List.
Payloads must be under 500 KB when using the Scan API. If your file is larger than the limit, consider using the file api, which is also available via the Python SDK.
We will ignore the second parameter as we do not have redaction configured for this request.
With the Nightfall API, you can redact and mask your findings. You can add a Redaction Config, as part of your Detection Rule. For more information on how to use redaction, and its specific options, please refer to the guide here.
Now we are ready to review the results from the Nightfall SDK to check if there is any sensitive data in our file. Since the results will be in a , we can use the built-in __repr__ functions to format the results in a user-friendly and readable manner.
All data and sample findings shown below are validated, non-sensitive, examples of sample data.
If there are no sensitive findings in our payload, the response will be as shown in the 'empty response' pane below:
And that's it 🎉
You are now ready to use the Python SDK for other scenarios.
get_violation to understand context and available remediation actionsReview sensitive findings: For top violations, use get_violation_findings to understand what data was exposed
Generate triage report: Create a prioritized list with specific next steps using take_action_on_violations
Get details for key incidents: Use the appropriate get_* tools for the most significant events
Generate report: Produce a structured report with executive summary, breakdowns by integration/severity, top incidents, trends, and recommendations
search_posture_eventsactor_email:[email]Get details on significant events: For high-risk items, use the appropriate get_* tools
Generate risk assessment: Produce a user profile with statistics, risk score, timeline, behavioral patterns, and recommendations
Execute remediation: Use take_action_on_violations with appropriate action (RESOLVE, BLOCK, DELETE, etc.)
Verify completion: Check get_violation_activity to confirm the action was recorded
Clarify formatting preferences: "Show as a table" or "Give me a bullet list"
Chain multiple steps in one request: "Search for violations, get details on the top 3, and show findings" is more efficient than three separate questions
Use date ranges to limit result sets when investigating recent incidents
Ask for pagination when dealing with large result sets to avoid overwhelming responses
Combine filters naturally: "high-risk GitHub violations from last week" is more efficient than multiple separate queries
Enable audit logging in your AI client to track MCP queries for compliance
Clarify formatting preferences: "Show as a table" or "Give me a bullet list"
curl --request POST \
--url https://api.nightfall.ai/v3/scan \
--header 'Accept: application/json' \
--header 'Authorization: Bearer NF-rEpLaCeM3w1ThYoUrNiGhTfAlLKeY123' \
--header 'Content-Type: application/json' \
--data '
{
"policy": {
"detectionRules": [
{
"detectors": [
{
"minNumFindings": 1,
"minConfidence": "VERY_LIKELY",
"displayName": "US Social Security Number",
"detectorType": "NIGHTFALL_DETECTOR",
"nightfallDetector": "US_SOCIAL_SECURITY_NUMBER"
},
{
"redactionConfig": {
"maskConfig": {
"charsToIgnore": [
"-"
],
"maskingChar": "X",
"maskRightToLeft":true,
"numCharsToLeaveUnMasked":4
}
},
"minNumFindings": 1,
"minConfidence": "VERY_LIKELY",
"displayName": "Credit Card Number",
"detectorType": "NIGHTFALL_DETECTOR",
"nightfallDetector": "CREDIT_CARD_NUMBER"
}
],
"name": "My Match Rule",
"logicalOp": "ANY"
}
]
},
"payload": [
"The customer social security number is 458-02-6124",
"No PII in this string",
"My credit card number is 5310-2768-6832-9293"
]
}
'// By default, the client reads your API key from the environment variable NIGHTFALL_API_KEY
const nfClient = new Nightfall();
const payload = [
"The customer social security number is 458-02-6124",
"No PII in this string",
"My credit card number is 5310-2768-6832-9293"
];
const policy = {
"detectionRules": [
{
"detectors": [
{
"minNumFindings": 1,
"minConfidence": "LIKELY",
"displayName": "US Social Security Number",
"detectorType": "NIGHTFALL_DETECTOR",
"nightfallDetector": "US_SOCIAL_SECURITY_NUMBER"
},
{
"redactionConfig": {
"maskConfig": {
"charsToIgnore": [
"-"
],
"maskingChar": "#"
}
},
"minNumFindings": 1,
"minConfidence": "LIKELY",
"displayName": "Credit Card Number",
"detectorType": "NIGHTFALL_DETECTOR",
"nightfallDetector": "CREDIT_CARD_NUMBER"
}
],
"name": "My Match Rule",
"logicalOp": "ANY"
}
]
};
const response = await nfClient.scanText(payload, policy);
if (response.isError) {
console.log(response.getError());
} else {
response.data.findings.forEach((finding) => {
if (finding.length > 0) {
finding.forEach((result) => {
console.log(`Finding: ${result.finding}, Confidence: ${result.confidence}`);
});
}
});
}// Some code>>> from nightfall import Confidence, DetectionRule, Detector, Nightfall
>>> # By default, the client reads the API key from the environment variable NIGHTFALL_API_KEY
>>> nightfall = Nightfall()
>>> # A rule contains a set of detectors to scan with
>>> cc = Detector(min_confidence=Confidence.LIKELY, nightfall_detector="CREDIT_CARD_NUMBER")
>>> ssn = Detector(min_confidence=Confidence.POSSIBLE, nightfall_detector="US_SOCIAL_SECURITY_NUMBER")
>>> detection_rule = DetectionRule([cc, ssn])
>>> payload = ["hello world", "my SSN is 678-99-8212", "4242-4242-4242-4242"]
>>> findings, _ = nightfall.scan_text( payload, detection_rules=[detection_rule]){
"findings": [
[
{
"finding": "458-02-6124",
"redactedFinding": "XXX-XXXX-XXXX-9293",
"detector": {
"name": "US Social Security Number",
"uuid": "e30d9a87-f6c7-46b9-a8f4-16547901e069"
},
"confidence": "VERY_LIKELY",
"location": {
"byteRange": {
"start": 39,
"end": 50
},
"codepointRange": {
"start": 39,
"end": 50
},
"rowRange": null,
"columnRange": null,
"commitHash": ""
},
"matchedDetectionRuleUUIDs": [],
"matchedDetectionRules": [
"My Match Rule"
]
}
],
[],
[
{
"finding": "5310-2768-6832-9293",
"redactedFinding": "XXXX-XXXX-XXXX-9293",
"detector": {
"name": "Credit Card Number",
"uuid": "74c1815e-c0c3-4df5-8b1e-6cf98864a454"
},
"confidence": "VERY_LIKELY",
"location": {
"byteRange": {
"start": 25,
"end": 44
},
"codepointRange": {
"start": 25,
"end": 44
},
"rowRange": null,
"columnRange": null,
"commitHash": ""
},
"redactedLocation": {
"byteRange": {
"start": 25,
"end": 44
},
"codepointRange": {
"start": 25,
"end": 44
},
"rowRange": null,
"columnRange": null,
"commitHash": ""
},
"matchedDetectionRuleUUIDs": [],
"matchedDetectionRules": [
"My Match Rule"
]
}
]
],
"redactedPayload": [
"",
"",
"My credit card number is XXXX-XXXX-XXXX-9293"
]
}import os
from nightfall import Confidence, DetectionRule, Detector, LogicalOp, Nightfallnightfall = Nightfall(os.environ['NIGHTFALL_API_KEY'])detection_rule_uuid = os.environ.get('DETECTION_RULE_UUID')payload = [
"The customer social security number is 458-02-6124",
"No PII in this string",
"My credit card number is 4916-6734-7572-5015"
]
result, _ = nightfall.scan_text(
payload,
detection_rule_uuids=[detection_rule_uuid]
)payload = [
"The customer social security number is 458-02-6124",
"No PII in this string",
"My credit card number is 4916-6734-7572-5015"
]
result, _ = nightfall.scan_text(
payload,
detection_rules=[
DetectionRule(
name="Sample_Detection_Rule",
logical_op=LogicalOp.ANY,
detectors=[
Detector(
min_confidence=Confidence.VERY_LIKELY,
min_num_findings=1,
display_name="Credit Card",
nightfall_detector="CREDIT_CARD_NUMBER",
),
Detector(
min_confidence=Confidence.VERY_LIKELY,
min_num_findings=1,
display_name="Social",
nightfall_detector="US_SOCIAL_SECURITY_NUMBER",
)
]
)
]
)[
[Finding(finding='458-02-6124', redacted_finding=None, before_context=None, after_context=None, detector_name='US social security number (SSN)', detector_uuid='e30d9a87-f6c7-46b9-a8f4-16547901e069', confidence=<Confidence.VERY_LIKELY: 'VERY_LIKELY'>, byte_range=Range(start=39, end=50), codepoint_range=Range(start=39, end=50), matched_detection_rule_uuids=['c67e3dd7-560e-438f-8c72-6ec54979396f'], matched_detection_rules=[])],
[],
[Finding(finding='4916-6734-7572-5015', redacted_finding=None, before_context=None, after_context=None, detector_name='Credit card number', detector_uuid='74c1815e-c0c3-4df5-8b1e-6cf98864a454', confidence=<Confidence.VERY_LIKELY: 'VERY_LIKELY'>, byte_range=Range(start=25, end=44), codepoint_range=Range(start=25, end=44), matched_detection_rule_uuids=['c67e3dd7-560e-438f-8c72-6ec54979396f'], matched_detection_rules=[])]
][
[Finding(finding='458-02-6124', redacted_finding=None, before_context=None, after_context=None, detector_name='Social', detector_uuid='e30d9a87-f6c7-46b9-a8f4-16547901e069', confidence=<Confidence.VERY_LIKELY: 'VERY_LIKELY'>, byte_range=Range(start=39, end=50), codepoint_range=Range(start=39, end=50), matched_detection_rule_uuids=[], matched_detection_rules=['Sample_Detection_Rule'])],
[],
[Finding(finding='4916-6734-7572-5015', redacted_finding=None, before_context=None, after_context=None, detector_name='Credit Card', detector_uuid='74c1815e-c0c3-4df5-8b1e-6cf98864a454', confidence=<Confidence.VERY_LIKELY: 'VERY_LIKELY'>, byte_range=Range(start=25, end=44), codepoint_range=Range(start=25, end=44), matched_detection_rule_uuids=[], matched_detection_rules=['Sample_Detection_Rule'])],
][[], [], []]The file scan API has first-class support for text extraction and scanning on all MIME types enumerated below.
Certain file types receive special handling, such as and , that results in more precise information about the location of findings within the source file.
application/json
application/x-ndjson
application/x-php
text/calendar
text/css
text/csv (treated as tabular data and may be redacted )
text/html
text/javascript
text/plain
text/tab-separated-values (treated as tabular data)
text/tsv (treated as tabular data)
text/x-php
application/pdf
application/vnd.openxmlformats-officedocument.presentationml.presentation
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet (treated as tabular data)
application/vnd.openxmlformats-officedocument.wordprocessingml.document
application/vnd.ms-excel (treated as )
application/bzip2
application/ear
application/gzip
application/jar
application/java-archive
application/tar+gzip
application/vnd.android.package-archive
application/war
application/x-bzip2
application/x-gzip
application/x-rar-compressed
application/x-tar
application/x-webarchive
application/x-zip-compressed
application/x-zip
application/zip
image/apng
image/avif
image/gif
image/jpeg
image/jpg
image/png
image/svg+xml
image/tiff
image/webp
The file scan API explicitly rejects requests with MIME types that are not conducive to extracting or scanning text. Sample rejected MIME types include:
application/photoshop
audio/midi
audio/wav
video/mp4
video/quicktime
File scans of Microsoft Office, Apache parquet, csv, and tab separated files will provide additional properties to locate findings within the document beyond the standard byteRange, codepointRange, and lineRange properties.
Findings will contain a columnRange and a rowRange that will allow you to identify the specific row and column within the tabular data wherein the finding is present.
This functionality is applicable to the following mime types:
text/csv
text/tab-separated-values
text/tsv
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
application/vnd.ms-excel
Apache parquet data files are also accepted.
Below is a sample match of a spreadsheet containing dummy PII where a SSN was detected in the 2nd column and 55th row.
Findings within csv files may be redacted.
To enable redaction in files, set the enableFileRedaction flag of your policy to "true"
The csv file will be redacted based on the configuration of the defaultRedactionConfig of the policy
Below is an example curl request for a csv file that has already been uploaded .
When results are sent to the location specified in the alertConfig (in this case an email address) a redactedFile property will be set with a fileURL in addition the findingsURL
This redacted file will be a modified version of the original csv file.
Below is an example of a redacted csv file.
Nightfall provides special handling for archives of Git repositories.
Nightfall will scan the repository history to discover findings in particular checkin, returning the hash for the checkin.
In order to scan the repository, you will need to create a clone, i.e.
git clone https://github.com/nightfallai/nightfall-go-sdk.git
This creates a clone of the Nightfall go SDK.
You will then need to create an archive that can be uploaded using Nightfall's file scanning sequence.
zip -r directory.zip directory
Note that in order to work, the hidden directory .github must be included in the archive.
When you initiate the file upload sequence with this file, you will receive scan results that contain the commitHash property filled in.
Using the Nightfall go SDK archive created above, a simple example would be to scan for URLs (i.e. strings starting with http:// or https://), which will send results such as the following:
Large repositories result in a large volume of data sent at once. We are working on changes to allow these and other large surges of data to be processed in a more controlled manner, and will increase the limit or remove it altogether once those changes are complete.
To retrieve the specific checkout, you will need to clone the repository, i.e.
git clone https://github.com/nightfallai/nightfall-go-sdk.git
You can then checkout the specific commit using the commit hash returned by Nightfall.
Note that you are in a 'detached HEAD' state when workin with this sort of check out of a repository.
CSV Files: Only the first 250,000 rows will be scanned.
Spreadsheet Files: Up to 100,000 rows per sheet will be scanned, with a maximum of 1 million rows across all tabs in multi-sheet spreadsheets.
PDF Files: Scanning is limited to the first 100 pages, including a maximum of 50 images within those pages.
Images: Images smaller than 5KB or larger than 50MB will be excluded from scanning.
Archive Files: A maximum of 1,000 files will be extracted and scanned. Files larger than 100MB requiring extraction will not be scanned.
{
"findings":[
{
"path":"Sheet1 (5)",
"detector":{
"id":"e30d9a87-f6c7-46b9-a8f4-16547901e069",
"name":"US social security number (SSN)",
"version":1
},
"finding":"624-84-9182",
"confidence":"LIKELY",
"location":{
"byteRange":{
"start":2505,
"end":2516
},
"codepointRange":{
"start":2452,
"end":2463
},
"lineRange":{
"start":55,
"end":55
},
"rowRange":{
"start":55,
"end":55
},
"columnRange":{
"start":2,
"end":2
},
"commitHash":""
},
"matchedDetectionRuleUUIDs":[
"950833c9-8608-4c66-8a3a-0734eac11157"
],
"matchedDetectionRules":[
]
},
...curl --request POST \
--url https://api.nightfall.ai/v3/upload/02a0c5e1-c950-4e28-a988-f6fffefc4205/scan \
--header 'Accept: application/json' \
--header 'Authorization: Bearer NF-<Your API Key>' \
--header 'Content-Type: application/json' \
--data '
{
"policy": {
"detectionRuleUUIDs": [
"950833c9-8608-4c66-8a3a-0734eac11157"
],
"alertConfig": {
"email": {
"address": "<your email addres>"
}
},
"defaultRedactionConfig": {
"maskConfig": {
"charsToIgnore": [
"-",
"@"
],
"maskingChar": "*"
}
},
"enableFileRedaction": true
},
"requestMetadata": "csv redaction test"
}
'{
"errors":null,
"findingsPresent":true,
"findingsURL":"https://files.nightfall.ai/asdfc5e1-c950-4e28-a988-f6fffefc4205.json?Expires=1655324479&Signature=zjo1nT-PECHC-fiTvAgdA8aDnceoY~6iGfzOBCcBjscKqOHnIar8hoH4gGufffiulBw5BpfJuvWwBW~lXO~ZNhN139LDwoTsfLJswJiQCB2Hj-Az0Em6go~1j8WBqCS8G0Gk17M-zcPedHGX3z~1pw8nm5sh6Pa-jJwfw9NIEiqmBb3Vdcj3J-~Wzag~ENV4499rnG299ee-ig5Ms1oVlzycb4YxzgTMrTL5Q07ozNenwFZcGDNQre1inLXmV-m8teLX-K3boklenp9KXiNDDV0wi74ADN-QfIR1q1oU7mEI1f3aVC3kju0QRErp2lsfs08EtZKLE3C4N17jDJdYcw__&Key-Pair-Id=K24YOPZ1EKX0YC",
"redactedFile":{
"fileURL":"https://files.nightfall.ai/asdfc5e1-c950-4e28-a988-f6fffefc4205-redacted.csv?Expires=1655324479&Signature=Hx8kRh88maLeStysy3fsLbFVG9VELEtfemtQe2lWUnFjAMd9HqlEksTmirqAWFWV4zPVUB73izlMj5cSer8v2N5ZCcnD3dz~nnwR4P5LewGJ2CQzGnDnXgh70HW5qp04gnUD-pYWp~bGPVspkJKCkl1zH-EoGonvcNVq3SNsVzOlsVIjep7Y7otQKEEyAZ7JmHiVfuBxrvn8pleuC5lEJ3f9miPyoRqH9DyPlNTJTIuijqe9q32Qcui2RsDR6IT-foFX52dy6rRa01ZV0gZMDWJokMlCr8Iu5An~qnhxC49bqTtI82oz9FcBaP-Yea8cq1TiAfGxX7CJ0~JeTLvr6g__&Key-Pair-Id=K24YOPZ1EKX0YC",
"validUntil":"2022-06-15T20:21:19.750990823Z"
},
"requestMetadata":"csv redaction test",
"uploadID":"02a0c5e1-c950-4e28-a988-f6fffefc4205",
"validUntil":"2022-06-15T20:21:19.723045787Z"
}name,email,phone,alphanumeric
Ulric Burton,*****@*************,*-***-***-****,TEL82EBM1GQ
Wade Jones,******************@***********,(********-****,VVF64PJV2EF
Molly Mccullough,*****************@**********,(********-****,OHO41SFZ2BR
Raja Riggs,************@**********,(********-****,UVD51JTE5NZ
Colin Carter,**********************@*********,(********-****,LNI34LLC5WV// Some code{
"findings":[
{
"path":"f607a067..53e59684/nightfall.go",
"detector":{
"id":"6123060e-2d9f-4f35-a7a1-743379ea5616",
"name":"URL"
},
"finding":"https://api.nightfall.ai/\"",
"confidence":"LIKELY",
"location":{
"byteRange":{
"start":142,
"end":168
},
"codepointRange":{
"start":142,
"end":168
},
"lineRange":{
"start":16,
"end":16
},
"rowRange":{
"start":0,
"end":0
},
"columnRange":{
"start":0,
"end":0
},
"commitHash":"53e59684d9778ceb0f0ed6a4b949c464c24d35ce"
},
"beforeContext":"tp\"\n\t\"os\"\n\t\"time\"\n)\n\nconst (\n\tAPIURL = \"",
"afterContext":"\n\n\tDefaultFileUploadConcurrency = 1\n\tDef",
"matchedDetectionRuleUUIDs":[
"cda0367f-aa75-4d6a-904f-0311209b3383"
],
"matchedDetectionRules":[
]
},
...cd nightfall-go-sdk
git checkout 53e59684d9778ceb0f0ed6a4b949c464c24d35ceCurrently, processing is limited to repositories with a total number of commits lower than 5000.
If the finding in a GitHub repository is considered to be sensitive, it should be considered compromised and appropriate mitigation steps (i.e. secrets should be rotated).
This guide describes how to use Nightfall with the Ruby programming language.
The example below will demonstrate how to use Nightfall’s text scanning functionality to verify whether a string contains sensitive PII using the Nightfall Python SDK.
To follow along, you will need:
A Nightfall API Key
An existing Detection Rule
Data to scan. Note that the API interprets data as plaintext, so you may pass it in any structured or unstructured format.
A local Ruby 2.6 or greater environment.
Start by creating a new file called nightfall_demo.rb
Now we will walk through the code step by step. If you'd like to skip ahead you can see the complete code sample at the bottom of this page.
We will be using a few built-in Ruby libraries to run this sample API script.
First, we will load some environment variables that will be used to interact with the Nightfall API. NIGHTFALL_API_KEY should be your Nightfall API Key, and NIGHTFALL_DETECTION_RULE_UUID should be the UUID for your existing Nightfall condition set.
Next, we will construct our payload to scan as an array. You can replace this with any data you'd like, or read plaintext from a file.
Next, we build the HTTP request headers and body using the environment variables that we previously defined.
Next, we build the HTTP object and make a request to the Nightfall API.
Lastly, we make the API request and process the response from Nightfall. If there are sensitive findings in the response we pretty-print them to the console. If there are no findings, we print a message to the console. Otherwise, if there is a problem with the HTTP request we print the status code and message to the console.
Now we can run our script:
If there are sensitive findings based on your Nightfall detection rule, you should see output similar to this in your console, corresponding to each of the 3 items inputted to scan in the payload.
Congrats 🎉. You've successfully scanned text for sensitive data with Ruby using the Nightfall API.
For your convenience, the complete Ruby code sample is shown below.
Nightfall's upload process is built to accommodate files of any size. Once files are uploaded, they may be scanned with and to detect potential violations.
Many users will find it more convenient to use our our to complete the upload process.
Uploading files using Client SDK libraries requires fewer steps as all the required API operations are wrapped in a single function call. Furthermore these SDKs handle all the programmatic logic necessary to send files in smaller chunks to Nightfall.
For users that are looking to understand the entire end-to-end, that is also outlined in this document. We will walk you through the order of operations necessary to upload the file.
Rather than implementing the for the upload functionality yourself, the Nightfall’s provide a single method that wraps the steps required to upload your file.
Below is an example of uploading a file from our and our .
In addition to using , you may define Detection Rules within the body of your scan method by either supplying:
the identifier of one of Nightfall's
the UUID of an a Detector defined through the UI
a Regular Expression
Policies allow customers to create templates for their most common workflows such as sending alerts when detection rules are triggered.
These policies may be through the dashboard or may be defined programmatically.
When defining an a Policy inline, in addition to specifying the Detection Rules (either by referencing the UUID of an existing Detection Rule or), you must define an alertConfig which will determine where findings are sent.
The alertConfig can be either:
an email address
a Word List.
Out of the box, Nightfall comes with an extensive library of native detectors.
In the example below two of Nightfall's native Detectors (detectorType = "NIGHTFALL_DETECTOR") are being used:
US_SOCIAL_SECURITY_NUMBER
CREDIT_CARD_NUMBER.
When defining a Detection Rule in line, you configure the minimum confidence level (minConfidence) and minimum number of times the match must be found (minNumFindings) for the rule to be triggered. .
In the payload body, you can see that we are submitting a list of three different strings to scan (payload). The first will trigger the U.S. Social Security Detector. The last will trigger the credit card Detector. The middle example will trigger neither.
For more information on the parameters related to redaction, see Using Redaction.
Below is the response payload to the previous request.
The following example shows a Detection Rule composed of two Detectors defined using regular expressions – one for the format of an International Standard Recording Code (ISRC) and one for the format of an International Standard Musical Work Code (ISWC) – matching either of which will trigger the Detection Rule (by using the logicalOp “Any”).
We will provide a payload of two strings, one of which will match the ISRC and one of which will match the ISWC.
The returned response demonstrates how findings are returned, with a finding per payload entry and the Detection Rule and Detector that matched the payload, if any.
The byte range that triggered the match is also provided. In the case of the 2nd item in the payload, since the match occurred at the beginning of the string, it has a location where the byteRange start is 0. In the case of the 3rd payload entry the location offset is 31.
The following example shows how a word list may be used instead of a regular expression.
Below is the resulting payload with the findings detected in our different payload strings.
Note that since the isCaseSensitive flag is set to "false" for the detector, so the first string in our payload matches a word from our word list.
Also note that the confidence level for a word list match defaults to "LIKELY" so you should not set a minConfidence level higher than that if you want matches to result.
# Load dependencies
require 'open-uri'
require 'net/http'
require 'json'# Load environment variables for Nightfall API
nightfall_api_key = ENV['NIGHTFALL_API_KEY']
detection_rule_uuid = ENV['NIGHTFALL_DETECTION_RULE_UUID']# Text data to scan
payload = [
"The customer social security number is 458-02-6124",
"No PII in this string",
"My credit card number is 4916-6734-7572-5015"
]# Configure detection settings
config = {
"config": {
"detectionRuleUUIDs": [detection_rule_uuid]
},
"payload": payload
}# Build API request
url = URI("https://api.nightfall.ai/v3/scan")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Accept"] = 'application/json'
request["Content-Type"] = 'application/json'
request["Authorization"] = "Bearer #{nightfall_api_key}"
request.body = config.to_json# Make API request
response = http.request(request)
# Parse response
if response.code.to_i == 200 and response.body['findings']
puts "This text contains sensitive data.\n\n"
puts JSON.pretty_generate(JSON.parse(response.body))
elsif response.code.to_i == 200
puts "No sensitive data found. Hooray!"
else
puts "Something went wrong -- Response #{response.code}."
endruby nightfall_demo.rbThis text contains sensitive data.
{
"findings": [
[
{
"finding": "458-02-6124",
"detector": {
"name": "US social security number (SSN)",
"uuid": "e30d9a87-f6c7-46b9-a8f4-16547901e069"
},
"confidence": "VERY_LIKELY",
"location": {
"byteRange": {
"start": 39,
"end": 50
},
"codepointRange": {
"start": 39,
"end": 50
}
},
"matchedDetectionRuleUUIDs": [
"996a3c12-35d1-48cb-b858-5ee0841c652d"
],
"matchedDetectionRules": [
]
}
],
[
],
[
{
"finding": "4916-6734-7572-5015",
"detector": {
"name": "Credit card number",
"uuid": "74c1815e-c0c3-4df5-8b1e-6cf98864a454"
},
"confidence": "VERY_LIKELY",
"location": {
"byteRange": {
"start": 25,
"end": 44
},
"codepointRange": {
"start": 25,
"end": 44
}
},
"matchedDetectionRuleUUIDs": [
"996a3c12-35d1-48cb-b858-5ee0841c652d"
],
"matchedDetectionRules": [
]
}
]
],
"redactedPayload": [
"",
"",
""
]
}
# nightfall_demo.rb
# Load dependencies
require 'open-uri'
require 'net/http'
require 'json'
# Load environment variables for Nightfall API
nightfall_api_key = ENV['NIGHTFALL_API_KEY']
detection_rule_uuid = ENV['NIGHTFALL_DETECTION_RULE_UUID']
# Text data to scan
payload = [
"The customer social security number is 458-02-6124",
"No PII in this string",
"My credit card number is 4916-6734-7572-5015"
]
# Configure detection settings
config = {
"config": {
"detectionRuleUUIDs": [detection_rule_uuid]
},
"payload": payload
}
# Build API request
url = URI("https://api.nightfall.ai/v3/scan")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Accept"] = 'application/json'
request["Content-Type"] = 'application/json'
request["Authorization"] = "Bearer #{nightfall_api_key}"
request.body = config.to_json
# Make API request
response = http.request(request)
# Parse response
if response.code.to_i == 200 and response.body['findings']
puts "This text contains sensitive data.\n\n"
puts JSON.pretty_generate(JSON.parse(response.body))
elsif response.code.to_i == 200
puts "No sensitive data found. Hooray!"
else
puts "Something went wrong -- Response #{response.code}."
endcurl --request POST \
--url https://api.nightfall.ai/v3/scan \
--header 'Authorization: Bearer NF-rEpLaCeM3w1ThYoUrNiGhTfAlLKeY123' \
--header 'Content-Type: application/json' \
--data '{
"policy": {
"detectionRules": [
{
"detectors": [
{
"detectorType": "NIGHTFALL_DETECTOR",
"nightfallDetector": "US_SOCIAL_SECURITY_NUMBER",
"minNumFindings": 1,
"minConfidence": "LIKELY",
"displayName": "US Social Security Number"
},
{
"detectorType": "NIGHTFALL_DETECTOR",
"nightfallDetector": "CREDIT_CARD_NUMBER",
"minNumFindings": 1,
"minConfidence": "LIKELY",
"displayName": "Credit Card Number",
"redactionConfig": {
"maskConfig": {
"maskingChar": "👀",
"charsToIgnore": ["-"]
}
}
}
],
"name": "My Match Rule",
"logicalOp": "ANY"
}
]
},
"payload": [
"The customer social security number is 458-02-6124",
"No PII in this string",
"My credit card number is 5310-2768-6832-9293"
]
}'{
"findings": [
[
{
"finding": "458-02-6124",
"detector": {
"name": "US Social Security Number",
"uuid": "e30d9a87-f6c7-46b9-a8f4-16547901e069"
},
"confidence": "VERY_LIKELY",
"location": {
"byteRange": {
"start": 39,
"end": 50
},
"codepointRange": {
"start": 39,
"end": 50
}
},
"matchedDetectionRuleUUIDs": [],
"matchedDetectionRules": [
"My Match Rule"
]
}
],
[],
[
{
"finding": "5310-2768-6832-9293",
"redactedFinding": "👀👀👀👀-👀👀👀👀-👀👀👀👀-👀👀👀👀",
"detector": {
"name": "Credit Card Number",
"uuid": "74c1815e-c0c3-4df5-8b1e-6cf98864a454"
},
"confidence": "VERY_LIKELY",
"location": {
"byteRange": {
"start": 25,
"end": 44
},
"codepointRange": {
"start": 25,
"end": 44
}
},
"redactedLocation": {
"byteRange": {
"start": 25,
"end": 44
},
"codepointRange": {
"start": 25,
"end": 44
}
},
"matchedDetectionRuleUUIDs": [],
"matchedDetectionRules": [
"My Match Rule"
]
}
]
],
"redactedPayload": [
"",
"",
"My credit card number is 👀👀👀👀-👀👀👀👀-👀👀👀👀-👀👀👀👀"
]
}curl --location --request POST 'https://api.nightfall.ai/v3/scan' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer NF-rEpLaCeM3w1ThYoUrNiGhTfAlLKeY123' \
--header 'Content-Type: application/json' \
--data-raw '{
"config": {
"detectionRules": [
{
"detectors": [
{
"regex": {
"isCaseSensitive": false,
"pattern": "[A-Z]{2}-?\\w{3}-?\\d{2}-?\\d{5}"
},
"minNumFindings": 1,
"minConfidence": "POSSIBLE",
"detectorType": "REGEX",
"displayName": "ISRC Code Detector"
},
{
"regex": {
"isCaseSensitive": false,
"pattern": "T-[0-9]{3}\\.[0-9]{3}\\.[0-9]{3}-[0-9]"
},
"minNumFindings": 1,
"minConfidence": "POSSIBLE",
"detectorType": "REGEX",
"displayName": "ISWC Code Detector"
}
],
"name": "ISRC and ISWC Code Detection Rule",
"logicalOp": "ANY"
}
]
},
"payload": [
"Non Matching Payload",
"US-S1Z-99-00001 is an example ISRC Code: ",
"The ISWC for Symphony No. 9 is T-905.029.737-5"
]
}
'{
"findings": [
[],
[
{
"finding": "US-S1Z-99-00001",
"detector": {
"name": "ISRC Code Detector",
"uuid": "d8be87c9-4b44-41fd-b78c-8d638fe56069"
},
"confidence": "LIKELY",
"location": {
"byteRange": {
"start": 0,
"end": 15
},
"codepointRange": {
"start": 0,
"end": 15
}
},
"matchedDetectionRuleUUIDs": [],
"matchedDetectionRules": [
"ISRC and ISWC Code Detection Rule"
]
}
],
[
{
"finding": "T-905.029.737-5",
"detector": {
"name": "ISWC Code Detector",
"uuid": "faf4c830-f2ac-4934-bf9c-ff20f5a6f420"
},
"confidence": "LIKELY",
"location": {
"byteRange": {
"start": 31,
"end": 46
},
"codepointRange": {
"start": 31,
"end": 46
}
},
"matchedDetectionRuleUUIDs": [],
"matchedDetectionRules": [
"ISRC and ISWC Code Detection Rule"
]
}
]
]
}curl --location --request POST 'https://api.nightfall.ai/v3/scan' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'x-api-key: NF-rEpLaCeM3w1ThYoUrNiGhTfAlLKeY123' \
--data-raw '{
"config": {
"detectionRules": [
{
"detectors": [
{
"wordList": {
"values": [
"cat",
"dog",
"rat"
],
"isCaseSensitive": false
},
"minNumFindings": 1,
"minConfidence": "POSSIBLE",
"displayName": "animals",
"detectorType": "WORD_LIST"
}
],
"name": "WordListExamples",
"logicalOp": "ANY"
}
]
},
"payload": [
"THE CAT SAT ON THE MAT",
"The dog and the rat are on the west bank of the river",
"No one here but use chickens"
]
}'{
"findings": [
[
{
"finding": "cat",
"detector": {
"name": "animals",
"uuid": "c033e224-034a-417f-9c0d-0c8d13f462bb"
},
"confidence": "LIKELY",
"location": {
"byteRange": {
"start": 4,
"end": 7
},
"codepointRange": {
"start": 4,
"end": 7
}
},
"matchedDetectionRuleUUIDs": [],
"matchedDetectionRules": [
"WordListExamples"
]
}
],
[
{
"finding": "dog",
"detector": {
"name": "animals",
"uuid": "c033e224-034a-417f-9c0d-0c8d13f462bb"
},
"confidence": "LIKELY",
"location": {
"byteRange": {
"start": 4,
"end": 7
},
"codepointRange": {
"start": 4,
"end": 7
}
},
"matchedDetectionRuleUUIDs": [],
"matchedDetectionRules": [
"WordListExamples"
]
},
{
"finding": "rat",
"detector": {
"name": "animals",
"uuid": "c033e224-034a-417f-9c0d-0c8d13f462bb"
},
"confidence": "LIKELY",
"location": {
"byteRange": {
"start": 16,
"end": 19
},
"codepointRange": {
"start": 16,
"end": 19
}
},
"matchedDetectionRuleUUIDs": [],
"matchedDetectionRules": [
"WordListExamples"
]
}
],
[]
],
"redactedPayload": [
"",
"",
""
]
}To run the node sample script you must compile it as TypesScript. Save it as a .ts file and run
tsc <yourfilename>.ts -lib ES2015,DOM
You can then run the resulting JavaScript file:
NIGHTFALL_API_KEY=<YourApiKey> node yourscriptname.js
Note that these examples use an email address to receive the results for simplicity.
You may also want to use a webhook. See Webhooks and Asynchronous Notifications for additional information on how to set up Webhook server to receive these results.
The upload process consists of 3 stages:
Once the upload is complete, you may initiate the file scan.
After we discuss each API call in the sequence, you will find a script that walks through the full sequence at the end of this guide.
POST /v3/upload
The first step in the process of scanning a binary file is to initiate an upload in order to get a fileId through the Initiate a File Upload endpoint.
As part of the initialization you must provide the total byte size of the file being uploaded.
You may also provide the mime-type, otherwise the system will attempt to determine it once the upload is complete.
The id of the returned JSON object will be used as the fileId in subsequent requests.
The chunkSize is the maximum number of bytes to upload during the uploading phase.
Use the Upload a Chunk of a File endpoint to upload the file contents in chunks.
The size of these chunks are determined by the chunkSize value returned by POST /upload endpoint used in the previous step.
Below is a simple example where the file is less than the chunkSize so may safely be uploaded with one call to the upload endpoint.
If your file's size exceeds the chunkSize, to upload the complete file you will need to send iterative requests as you read portions of the file's contents. This means you will send multiple requests to the upload endpoint as shown above. As you do so, you will be updating the value of the X-Upload-Offset header based on the portion of the file being sent.
Each request should send a chunk of the file exactly chunkSize bytes long except for the final uploaded chunk. The final uploaded chunk is allowed to contain fewer bytes as the remainder of the file may be less than the chunkSize returned by the initialization step.
The request body should be the contents of the chunk being uploaded.
The value of the X-UPLOAD-OFFSET header should be the byte offset specifying where to insert the data into the file as an integer. This byte offset is zero-indexed.
Successful calls to this endpoint return an empty response with an HTTP status code of 204
See the full example script below for an illustration as to how this upload process can be done programmatically.
POST /v3/upload/<uploadUUID>/finish
Once all chunks are uploaded, mark the upload as completed using the Complete a File Upload endpoint.
When an upload completes successfully, the returned payload will indicate the mimeType the system determined to file to be if it was not provided during upload initialization.
Once a file has been marked as completed, you may initiate a scan of the uploaded file.
After an upload is finalized, it can be scanned against a Detection Policy. A Detection Policy represents a pairing of:
a webhook URL
a set of detection rules to scan data against
The scanning process is asynchronous, with results being delivered to the webhook URL configured on the detection policy. See Webhooks and Asynchronous Notifications for more information about creating a Webhook server.
Exactly one policy should be provided in the request body, which includes a webhookURL to which the callback will be made once the file scan has been completed (this must be an HTTPS URL) as well as a Detection Rule as either an a list of UUIDs or as a rule that has been defined in-line.
You may also supply a value to the requestMetadata field to help identify the input file upon receiving a response to your webhook. This field has a maximum length 10 KB.
Below is a sample Python script that handles the complete sequence of API calls to upload a file using a path specified as an argument.
>>> from nightfall import Confidence, DetectionRule, Detector, Nightfall, EmailAlert, AlertConfig
>>> import os
>>> # use your API Key here
>>> nightfall = Nightfall("NF-y0uRaPiK3yG03sH3r3")
>>> # A rule contains a set of detectors to scan with
>>> cc = Detector(min_confidence=Confidence.LIKELY, nightfall_detector="CREDIT_CARD_NUMBER")
>>> ssn = Detector(min_confidence=Confidence.POSSIBLE, nightfall_detector="US_SOCIAL_SECURITY_NUMBER")
>>> detection_rule = DetectionRule([cc, ssn])
>>> # The scanning is done asynchronously, so provide a valid email address as the simplest way of getting results
>>> alertconfig = alert_config=AlertConfig(email=EmailAlert("whatever@example.com"))
>>> # Upload the file and start the scan.
>>> id, message = nightfall.scan_file( "./README.md", detection_rules=[detection_rule],
>>> print("started scan", id, message)//this script assumes the node sdk has been installed locally with `npm install` and `npm run build`
import { Nightfall } from "./nightfall-nodejs-sdk/dist/nightfall.js";
import { Detector } from "./nightfall-nodejs-sdk/dist/types/detectors.js";
// By default, the client reads your API key from the environment variable NIGHTFALL_API_KEY
const uploadit = async() => {
var data = null;
const nfClient = new Nightfall();
try{
const response = await nfClient.scanFile('./README.md', {
detectionRules: [
{
name: 'Secrets Scanner',
logicalOp: 'ANY',
detectors: [
{
minNumFindings: 1,
minConfidence: Detector.Confidence.Possible,
displayName: 'Credit Card Number',
detectorType: Detector.Type.Nightfall,
nightfallDetector: 'CREDIT_CARD_NUMBER',
},
],
},
],
alertConfig: {
email: {
address: "whatever@example.com"
}
}
});
if (response.isError) {
data = response.getError();
}
else{
data = (response.data.id);
}
}
catch(e){
console.log(e);
}
return data;
}
uploadit().then(data => console.log(data));curl --location --request POST 'https://api.nightfall.ai/v3/upload' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer NF-rEpLaCeM3w1ThYoUrNiGhTfAlLKeY123' \
--data-raw '{
"fileSizeBytes": 73891,
"mimeType" : "image/png"
}'{
"id": "f9dbdb15-c9fa-46ff-86ec-cd5c09aa550d",
"fileSizeBytes": 73891,
"chunkSize": 10485760,
"mimeType": "image/png"
}PATCH /v3/upload/<uploadUUID>curl --location --request PATCH 'https://api.nightfall.ai/v3/upload/f9dbdb15-c9fa-46ff-86ec-cd5c09aa550d' \
--header 'X-Upload-Offset: 0' \
--header 'Content-Type: application/octet-stream' \
--header 'Authorization: Bearer NF-rEpLaCeM3w1ThYoUrNiGhTfAlLKeY123' \
--data-binary '@/Users/myname/Documents/work/Nightfall/Nightfall Upload Sequence.png'curl --location --request POST 'https://api.nightfall.ai/v3/upload/f9dbdb15-c9fa-46ff-86ec-cd5c09aa550d/finish' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer NF-rEpLaCeM3w1ThYoUrNiGhTfAlLKeY123' \
--data-raw '""'{
"id": "152848af-2ac9-4e0a-8563-2b82343d964a",
"fileSizeBytes": 2349,
"chunkSize": 10485760,
"mimeType": "application/zip"
}curl --request POST \
--url https://api.nightfall.ai/v3/upload/f9dbdb15-c9fa-46ff-86ec-cd5c09aa550d/scan \
--header 'Accept: application/json' \
--header 'Authorization: Bearer NF-rEpLaCeM3w1ThYoUrNiGhTfAlLKeY123' \
--header 'Content-Type: application/json' \
--data '
{
"policy": {
"detectionRuleUUIDs": [
"950833c9-8608-4c66-8a3a-0734eac11157"
],
"webhookURL": "https://mycompany.org/webhookservice"
},
"requestMetadata": "your file metadata"
}
'from os import getenv, path
import fire
import requests
BASE_UPLOAD_URL = getenv("FILE_UPLOAD_HOST", "http://api.nightfall.ai/v3")
NF_API_KEY = getenv("NF_API_KEY")
def upload(filepath, mimetype, policy_uuid):
"""Upload the given file using the provided MIMEType and PolicyUUID.
Arguments:
file_path -- an absolute or relative path to the file that will be
uploaded to the API.
mimetype -- (optional) The mimetype of the file being uploaded.
policy_uuid -- The UUID corresponding to an existing policy. This
policy must be active and have a webhook URL associated with it.
"""
default_headers = {
"Authorization": F"Bearer {NF_API_KEY}",
}
# =*=*=*=*=* Initiate Upload =*=*=*=*=*=*
file_size = path.getsize(filepath)
upload_request_body = {"fileSizeBytes": file_size, "mimeType": mimetype}
r = requests.post(F"{BASE_UPLOAD_URL}/upload",
headers=default_headers,
json=upload_request_body)
upload = r.json()
if not r.ok:
raise Exception(F"Unexpected error initializing upload - {upload}")
# =*=*=*=*=*=* Upload Chunks =*=*=*=*=*=*
chunk_size = upload["chunkSize"]
i = 0
with open(filepath, "rb") as file:
while file.tell() < file_size:
upload_chunk_headers = {
**default_headers,
"X-UPLOAD-OFFSET": str(file.tell())
}
r = requests.patch(F"{BASE_UPLOAD_URL}/upload/{upload['id']}",
headers=upload_chunk_headers,
data=file.read(chunk_size))
if not r.ok:
raise Exception(F"Unexpected error uploading chunk - {r.text}")
i += 1
# =*=*=*=*=*=* Finish Upload =*=*=*=*=*=*
r = requests.post(F"{BASE_UPLOAD_URL}/upload/{upload['id']}/finish",
headers=default_headers)
if not r.ok:
raise Exception(F"Unexpected error finalizing upload - {r.text}")
# =*=*=*=*=* Scan Uploaded File =*=*=*=*=*
r = requests.post(F"{BASE_UPLOAD_URL}/upload/{upload['id']}/scan",
json={"policyUUID": policy_uuid},
headers=default_headers)
if not r.ok:
raise Exception(F"Unexpected error initiating scan - {r.text}")
print("Scan Initiated Successfully - await response on configured webhook")
quota_remaining = r.headers.get('X-Quota-Remaining')
if quota_remaining is not None and int(quota_remaining) <= 0:
print(F"Scan quota exhausted - Quota will reset on {r.headers['X-Quota-Period-End']}")
if __name__ == "__main__":
fire.Fire(upload)Nightfall will verify that the webhook URL is valid before launching its asynchronous scan by issuing a challenge.
a webhook url
a url to a SIEM host as well authentication and other headers
Below is a simple example of a payload with a policy that will send alerts to an email address that you would use with our endpoint for .
You will receive the following response:
Note that you may also use a pre-defined policy defined under Developer Platform > Overview > Policies by copying the Policy UUID and sending a request as shown below.
The following payload will be sent to the given email address with the subject "🚨 Findings Detected by Nightfall! 🚨" as an attachment with the name nightfall-findings.json:
This attachment has the same content as the response payload to the initial request.
Note that the sender address will be no-reply@nightfall.ai
This email address will not respond to messages sent to it.
Policies also allow you to send findings to a callback designated URL using the url property of the alertConfig object.
This mechanism allows you to programmatically consume findings and the data sent will contain sensitive information as well as additional metadata like the location of the findings in the payload. For this reason the URL must be an HTTPS URL and the service backing it be implemented to properly respond with your Webhook signing key and act as a Webhook Server.
Below is what Webhook URL should like in your policy's alertConfig in a payload sent to our endpoint used for scanning plain text.
Another option supported by Policies is sending finding data to a designated Slack channel.
This feature requires that you have configured the Nightfall Slack integration.
Below is a sample payload for scanning plain text.
Below is an example as to how the violation will appear in Slack.
See the section on Slack in the overview on Alerting for more details.
SIEM (pronounced “sim”) is a combination of security information management (SIM) and security event management systems. SIEM technology collects event log data for analysis in order to provide visibility into network activity.
It is possible to send findings from a policy to a SIEM service such as LogRhythm, SumoLogic, or Splunk using the siem alertConfig.
This configuration will require a URL to a collector that uses an HTTPS endpoint.
Note that the URL for the siem alertConfig must:
use the HTTPS scheme
be able to accept requests made with the POST verb
respond with a 200 status code upon receipt of the event
See the documentation for your SIEM service for how to set up this URL.
Unlike the url alertConfig option, the siem alertConfig does not require that the endpoint for the service implement a custom challenge response. Events sent to the siem alertConfig endpoint contain a subset of what is sent to the url alertConfig. Furthermore the findings are sent in a redacted form similar to Slack or email alerts.
In addition to the URL, you may provide headers such as those that are used for authorization.
The headers in the SIEM alertConfig are divided into sensitiveHeaders and plainTextHeaders header mappings.
The sensitiveHeaders field is specifically for header values like authentication. Nightfall ensures that these header values are always hidden in our service. They are never logged or saved in analytic events.
You can use plainTextHeaders for all other type of information you would like passed along with Nightfall alerts to you HTTP endpoint. Nightfall assumes that the values stored plainTextHeaders do not contain any sensitive information so we do not take any action to hide or protect these values.
Below is an example of a payload using a siem alertConfig.
A policy may be configured with default redaction rules as a defaultRedactionConfig that will affect the content of the redactedPayload field of the content that is sent to the alert locations specified in the policy alertConfig. Note that this redaction does not affect the findings themselves.
These redaction rules will be applied to Detection Rules that do not have a specified redaction configuration.
The redactionConfig specified must be one and only one of the four available redaction types:
maskConfig
infoTypeSubstitutionConfig
substitutionConfig
cryptoConfig
For more information on Redactions see: Using Redaction
Below is a simple example of a payload for scanning plain text using a policy set up to use a defaultRedactionConfig
In additional to a defaultRedactionConfig it is possible to set the number of bytes to include as before and after a given finding as the contextBytes. This context can provide meaning to how the finding appears within the text to allow human readers to better understand the meaning of the finding. The maximum value for contextBytes is 40.
{
"policy": {
"detectionRules": [
{
"detectors": [
{
"detectorType": "NIGHTFALL_DETECTOR",
"nightfallDetector": "US_SOCIAL_SECURITY_NUMBER",
"minNumFindings": 1,
"minConfidence": "LIKELY",
"displayName": "US Social Security Number"
}
],
"name": "SSN Match Detection Rule",
"logicalOp": "ALL"
}
],
"contextBytes": 5,
"alertConfig": {
"email": {
"address": "youremail@nightfall.ai"
}
}
},
"payload": [
"The customer's social security number is 555-55-5555",
"No SSN in this string"
]
}{
"findings": [
[
{
"finding": "555-55-5555",
"beforeContext": "r is ",
"detector": {
"name": "US Social Security Number",
"uuid": "e30d9a87-f6c7-46b9-a8f4-16547901e069"
},
"confidence": "VERY_LIKELY",
"location": {
"byteRange": {
"start": 41,
"end": 52
},
"codepointRange": {
"start": 41,
"end": 52
},
"rowRange": null,
"columnRange": null,
"commitHash": ""
},
"matchedDetectionRuleUUIDs": [],
"matchedDetectionRules": [
"SSN Match Detection Rule"
]
}
],
[]
],
"redactedPayload": [
"",
""
]
}curl --request POST \
--url https://api.nightfall.ai/v3/scan \
--header 'accept: application/json' \
--header 'authorization: Bearer <InsertYourApiKeyHere>' \
--header 'content-type: application/json' \
--data '
{
"policyUUIDs": [
"2b2ced32-80c3-4a89-8757-489743ec4640"
],
"payload": [
"My payload to scan"
]
}
'{
"redactedPayload": [
"",
""
],
"findings": [
[
{
"confidence": "LIKELY",
"matchedDetectionRules": [
"SSN Match Detection Rule"
],
"matchedDetectionRuleUUIDs": [],
"location": {
"codepointRange": {
"start": 41,
"end": 52
},
"rowRange": null,
"byteRange": {
"start": 41,
"end": 52
},
"columnRange": null,
"commitHash": ""
},
"finding": "555-55-5555",
"detector": {
"name": "SSN Match Detector",
"uuid": "7270ccd5-07c5-44e5-b280-c768e0028963"
},
"beforeContext": "r is "
}
],
[]
]
}
{
"policy": {
"detectionRuleUUIDs": [
"c8d43147-0a63-4c01-8a57-83d8108422f5"
],
"alertConfig": {
"url": {
"address": "https://mywebhookurl.com"
}
}
},
"payload": [
"The customer's social security number is 555-55-5555"
]
}{
"policy": {
"detectionRules": [
{
"detectors": [
{
"detectorType": "NIGHTFALL_DETECTOR",
"nightfallDetector": "US_SOCIAL_SECURITY_NUMBER",
"minNumFindings": 1,
"minConfidence": "LIKELY",
"displayName": "US Social Security Number"
}
],
"name": "Simple SSN Match Detection Rule",
"logicalOp": "ALL"
}
],
"alertConfig": {
"slack": {
"target": "#securityalert"
}
}
},
"payload": [
"The customer's social security number is 555-55-5555",
"No SSN in this string"
]
}{
"policy": {
"detectionRules": [
{
"detectors": [
{
"nightfallDetector": "CREDIT_CARD_NUMBER",
"detectorType": "NIGHTFALL_DETECTOR",
"minConfidence": "POSSIBLE",
"minNumFindings": 1
}
],
"logicalOp": "ALL"
}
],
"alertConfig": {
"email": {
"address": "<your email>"
},
"siem": {
"sensitiveHeaders": {
"Authorization": "Splunk <your token value>"
},
"address": "https://http-inputs-<yourhost>.splunkcloud.com:8088/services/collector/event"
}
}
},
"payload": [
"4916-6734-7572-5015 is my credit card number",
"This string does not have any sensitive data",
"my api key is yr+ZWwIZp6ifFgaHV8410b2BxbRt5QiAj1EZx1qj and my 💳 credit card number 💰 is 30204861594838"
]
}
{
"policy": {
"detectionRules": [
{
"detectors": [
{
"detectorType": "NIGHTFALL_DETECTOR",
"nightfallDetector": "US_SOCIAL_SECURITY_NUMBER",
"minNumFindings": 1,
"minConfidence": "LIKELY",
"displayName": "US Social Security Number"
}
],
"name": "Simple SSN Match Detection Rule",
"logicalOp": "ALL"
}
],
"defaultRedactionConfig": {
"maskConfig": {
"charsToIgnore": [
"-"
],
"maskingChar": "#",
"numCharsToLeaveUnmasked": 4,
"maskLeftToRight": true
}
},
"contextBytes": 5,
"alertConfig": {
"email": {
"address": "eric@nightfall.ai"
}
}
},
"payload": [
"The customers social security number is 555-55-5555",
"No SSN in this string"
]
}The policy object supersedes the config object. The use of config objects will still continue to be supported, but its use should be considered deprecated. If you specify policy object you cannot also specify a config object.
Also note that previous iterations of the API allowed for a simple list of policyUUIDs to be specified instead of of a policy
To prevent misuse and ensure the stability of our platform, we enforce a rate limit on an API Key and endpoint basis, similar to the way many other APIs enforce rate limits.
When operating under our Free plan, accounts and their corresponding API Keys have a rate limit of 5 requests per second on average, with support for bursts of 15 requests per second. If you upgrade to a paid plan – the Enterprise plan – this rate increases to a limit of 10 requests per second on average and bursts of 50 requests per second.
The Nightfall API follows standard practices and conventions to signal when these rate limits have been exceeded.
Successful requests return a header X-Rate-Limit-Remaining with the integer number of requests remaining before errors will be returned to the client.
When your application exceeds the rate limit for a given API endpoint, the Nightfall API will return an HTTP "Too Many Requests.” If your use case requires increased rate limiting, please reach out to
Additionally, these unsuccessful requests return the number of seconds to wait before retrying the request in a Header.
Your Request Rate Limiting throttles how frequently you can make requests to the API. You can monitor your rate limit usage via the `X-Rate-Limit-Remaining` header, which tells you how many remaining requests you can make within the next second before being throttled.
Your Quota limits how many bytes of data you're permitted to scan within a given period. Your current remaining quota and the end of your current quota period are denoted by the following response headers.
The Nightfall API is capable of returning a redacted version of your scanned text when a Detector is triggered.
This functionality allows you to hide potentially sensitive information while retaining the original context in which that information appeared.
In order to redact content, when you call the scan endpoint you must provide a RedactionConfig as part of the definition of your Detection Rule.
You may specify one of the following different methods to redact content:
apply (e.g. asterisks)
substitute a
policypolicyUUIDspolicy
Free
5
15
Enterprise
10,
50,
X-Quota-Remaining
string
The bytes remaining in your quota for this period. Will be reset to the amount specified in your billing plan at the end of your quota cycle.
X-Quota-Period-End
substitute the triggered (referred to as "InfoType substitution")
use
A RedactionConfig is defined per Detector in a Detection Rule, allowing you to specify a different redaction method for each type of Detector in the rule.
By default, the redaction feature will return both the sensitive finding and the redacted version of that finding. You may set the removeFinding field to true if you want only the redacted version of the finding returned in the response.
Specifying a MaskConfig as part of your RedactionConfig substitutes a character for each character in the matched text. By default the masking character is an asterisk (*). You may specify an alternate character to use instead (maskingChar).
You may also choose to only mask a portion of the original text by specifying a number of characters to leave unmasked (numCharsToLeaveUnmasked). For instance, if you want to mask all but the last 4 digits of a credit card number, set this value to 4 so that the redacted finding would be rendered as ***************4242.
In the case where you want to leave characters unmasked at the front of the string you may use the maskRightToLeft flag. This flag determines if masking is applied right to left (*****/1984) instead of left to right (01/01*****). By default, this value is false.
Below is an example of how a RedactionConfig would be configured to redact the text that triggers a DATE_OF_BIRTH Detector such that the text 01/11/1995 becomes ??/??/??95
The SubstitutionConfig substitutes a sensitive finding with the value assigned to the property substitutionPhrase.
If no value is assigned to substitutionPhrase, the finding will be replaced with an empty string.
It is possible to replace a sensitive finding with the name of the NIGHTFALL_DETECTOR that triggered it by using an InfoTypeSubstitutionConfig.
If you use the built in credit card Detector, the string 4242-4242-4242-4242 will be redacted to [CREDIT_CARD_NUMBER]
This config is only valid for Detector's with a detectorType of NIGHTFALL_DETECTOR.
A CryptoConfig will encrypt a sensitive finding with a public key (provided as the publicKey property of the config) using RSA encryption.
Note that you are responsible for passing public keys for encryption and handling any decryption of the response payload. Nightfall will not store your keys.
Below is an example of a CryptoConfig being used to redact an EMAIL_ADDRESS detector.
The results of applying redactions are returned in the response payload for requests made to the as both part of an array named redactedPayload as well as additional properties of the finding object.
The original input payload with redactions made inline are returned as a list of strings under the redactedPayload property. Each item in the list of redacted payloads corresponds to the list of strings in the original input payload and, if a Detector was triggered, it will contain a redacted version of that corresponding string.
If an item in the input payload did not have any findings, the entry for that index will be an empty string ("").
The redactedPayload property is omitted if no RedactionConfig was provided.
Additionally, the fields redactedFinding and redactedLocation are added to the finding object when the redaction feature is invoked.
The redactedFinding field contains the redacted version of only the text of the finding without its surrounding context. This is useful when you are masking a portion of the text that triggered a Detector.
The redactedLocation property will be returned as part of the finding that corresponds to an item in the payload. This may be distinct from the location property that is returned for a finding by default.
In the unlikely case where there are findings that overlap, Nightfall will default to replacing the text of the overlapping findings with [REDACTED BY NIGHTFALL].
The following example shows how the redaction functionality may be invoked, with a variety of different redaction methods applied to the different Detectors being used.
You can see in the response how the RedactionConfig associated with the various Detectors affects the different findings.
Note that because the 2nd item the payload matches multiple detectors, the redacted text in the redactedPayload property becomes [REDACTED BY NIGHTFALL]
datetime
the date and time at which your quota will be reset, encoded as a string in the RFS-3339 format.
{
"minNumFindings":1,
"minConfidence":"POSSIBLE",
"detectorType":"NIGHTFALL_DETECTOR",
"nightfallDetector":"DATE_OF_BIRTH",
"redactionConfig":{
"maskConfig":{
"charsToIgnore":[
"/"
],
"maskingChar":"?",
"maskRightToLeft":true,
"numCharsToLeaveUnMasked":2
}
}
}{
"minNumFindings":1,
"minConfidence":"POSSIBLE",
"detectorType":"NIGHTFALL_DETECTOR",
"nightfallDetector":"EMAIL_ADDRESS",
"displayName":"email",
"redactionConfig":{
"cryptoConfig":{
"publicKey":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAydYMwOYUGyBXDgHkzv19YR/dYQES4kYTMUps39qv/amNDywz4nsBDvCUqUvcN3nEpplHlYGH5ShSeA4G/FcmRqynSLVyFPZat/8E7n+EeHsgihFrr8oDWo5UBjCwRinTrC0m11q/5SeNzwVCWkf9x40u94QBz13dQoa9yPwaZBX5uBzyH86R7yeZHpad2cLq0ltpmJ3j5UfsFilkOb3JB60TNpNDdfabprot/y30CEnDDOgAXGtV1m0AhQpQjKRnkUs39DntqSbS+i0UgbyqzEGNUkeR1WsotXekW4KnbWA7k6S8SfkO27vnTSY5b9g/KKaOdysn5YaWJPfTVT/nywIDAQAB\n-----END PUBLIC KEY-----"
}
}
}curl --location --request POST 'https://api.nightfall.ai/v3/scan' \
--header 'x-api-key: NF-rEpLaCeM3w1ThYoUrNiGhTfAlLKeY123' \
--header 'Content-Type: text/plain' \
--data-raw '{
"payload":[
"my ssn is 123-45-5555 and date of birth is 01/11/1995 and my credit card number is 4242 4242 4242 4242 and my email is james@gmail.com.",
"my date of birth is 03 23 4242 4242 4242 4242 amex"
],
"policy":{
"detectionRules":[
{
"detectors":[
{
"minNumFindings":1,
"minConfidence":"POSSIBLE",
"detectorType":"NIGHTFALL_DETECTOR",
"nightfallDetector":"CREDIT_CARD_NUMBER",
"displayName":"cc",
"redactionConfig":{
"infoTypeSubstitutionConfig":{
},
"removeFinding":true
}
},
{
"minNumFindings":1,
"minConfidence":"POSSIBLE",
"detectorType":"NIGHTFALL_DETECTOR",
"nightfallDetector":"US_SOCIAL_SECURITY_NUMBER",
"displayName":"ssn",
"redactionConfig":{
"substitutionConfig":{
"substitutionPhrase":"*REDACTED*"
}
}
},
{
"minNumFindings":1,
"minConfidence":"POSSIBLE",
"detectorType":"NIGHTFALL_DETECTOR",
"nightfallDetector":"EMAIL_ADDRESS",
"displayName":"email",
"redactionConfig":{
"cryptoConfig":{
"publicKey":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAydYMwOYUGyBXDgHkzv19YR/dYQES4kYTMUps39qv/amNDywz4nsBDvCUqUvcN3nEpplHlYGH5ShSeA4G/FcmRqynSLVyFPZat/8E7n+EeHsgihFrr8oDWo5UBjCwRinTrC0m11q/5SeNzwVCWkf9x40u94QBz13dQoa9yPwaZBX5uBzyH86R7yeZHpad2cLq0ltpmJ3j5UfsFilkOb3JB60TNpNDdfabprot/y30CEnDDOgAXGtV1m0AhQpQjKRnkUs39DntqSbS+i0UgbyqzEGNUkeR1WsotXekW4KnbWA7k6S8SfkO27vnTSY5b9g/KKaOdysn5YaWJPfTVT/nywIDAQAB\n-----END PUBLIC KEY-----"
}
}
},
{
"minNumFindings":1,
"minConfidence":"POSSIBLE",
"detectorType":"NIGHTFALL_DETECTOR",
"nightfallDetector":"DATE_OF_BIRTH",
"redactionConfig":{
"maskConfig":{
"charsToIgnore":[
"/"
],
"maskingChar":"?",
"maskRightToLeft":true,
"numCharsToLeaveUnMasked":2
}
}
}
],
"name":"cc",
"logicalOp":"ANY"
}
]
}
}'{
"findings":[
[
{
"finding":"james@gmail.com",
"redactedFinding":"X8QL0mZGHZ+N47nPEccjsLHf2F/5cFqjF16P6wgYJhy8IaxHipHWMBRAufKR4T8FFkvTuTEanu6ZAA+V8NTkNmTLxHarcWPSVClJ8kjXAPltLuR4I2H4eeT+sWEvUP3ik/BF1KcxRpsYWDQO1bNYk+WReXkWlW72Q7rbWuTGFj2uDFCPS+DUraDh9wNBsMPELFOnh1GSQIKCp9U5GMp/kkpo/0idh83RVHXyjZPT4ReKEST2oG2lQ9UuP5LJy/mHX1VYgd8DwlETn8nkhqJ1T0mGs6kHSh22G6N0ic0PjHnj73RiMnQdPwlLw3qyPmFf6RRLKtFuzmFan8ZGtZhcKA==",
"detector":{
"name":"email",
"uuid":"c0235299-0f26-4ad6-ad8c-71f83daf44e9"
},
"confidence":"VERY_LIKELY",
"location":{
"byteRange":{
"start":120,
"end":135
},
"codepointRange":{
"start":120,
"end":135
},
"rowRange":null,
"columnRange":null,
"commitHash":""
},
"redactedLocation":{
"byteRange":{
"start":120,
"end":135
},
"codepointRange":{
"start":120,
"end":135
},
"rowRange":null,
"columnRange":null,
"commitHash":""
},
"matchedDetectionRuleUUIDs":[
],
"matchedDetectionRules":[
"cc"
]
},
{
"finding":"01/11/1995",
"redactedFinding":"??/??/??95",
"detector":{
"name":"DATE_OF_BIRTH",
"uuid":"540856cb-99cb-42e7-b8aa-cd4f22f019d7"
},
"confidence":"LIKELY",
"location":{
"byteRange":{
"start":43,
"end":53
},
"codepointRange":{
"start":43,
"end":53
},
"rowRange":null,
"columnRange":null,
"commitHash":""
},
"redactedLocation":{
"byteRange":{
"start":43,
"end":53
},
"codepointRange":{
"start":43,
"end":53
},
"rowRange":null,
"columnRange":null,
"commitHash":""
},
"matchedDetectionRuleUUIDs":[
],
"matchedDetectionRules":[
"cc"
]
},
{
"finding":"",
"redactedFinding":"[CREDIT_CARD_NUMBER]",
"detector":{
"name":"cc",
"uuid":"74c1815e-c0c3-4df5-8b1e-6cf98864a454"
},
"confidence":"VERY_LIKELY",
"location":{
"byteRange":{
"start":84,
"end":103
},
"codepointRange":{
"start":84,
"end":103
},
"rowRange":null,
"columnRange":null,
"commitHash":""
},
"redactedLocation":{
"byteRange":{
"start":84,
"end":103
},
"codepointRange":{
"start":84,
"end":103
},
"rowRange":null,
"columnRange":null,
"commitHash":""
},
"matchedDetectionRuleUUIDs":[
],
"matchedDetectionRules":[
"cc"
]
},
{
"finding":"123-45-5555",
"redactedFinding":"*REDACTED*",
"detector":{
"name":"ssn",
"uuid":"e30d9a87-f6c7-46b9-a8f4-16547901e069"
},
"confidence":"VERY_LIKELY",
"location":{
"byteRange":{
"start":10,
"end":21
},
"codepointRange":{
"start":10,
"end":21
},
"rowRange":null,
"columnRange":null,
"commitHash":""
},
"redactedLocation":{
"byteRange":{
"start":10,
"end":21
},
"codepointRange":{
"start":10,
"end":21
},
"rowRange":null,
"columnRange":null,
"commitHash":""
},
"matchedDetectionRuleUUIDs":[
],
"matchedDetectionRules":[
"cc"
]
}
],
[
{
"finding":"",
"redactedFinding":"[CREDIT_CARD_NUMBER]",
"detector":{
"name":"cc",
"uuid":"74c1815e-c0c3-4df5-8b1e-6cf98864a454"
},
"confidence":"VERY_LIKELY",
"location":{
"byteRange":{
"start":26,
"end":45
},
"codepointRange":{
"start":26,
"end":45
},
"rowRange":null,
"columnRange":null,
"commitHash":""
},
"redactedLocation":{
"byteRange":{
"start":26,
"end":45
},
"codepointRange":{
"start":26,
"end":45
},
"rowRange":null,
"columnRange":null,
"commitHash":""
},
"matchedDetectionRuleUUIDs":[
],
"matchedDetectionRules":[
"cc"
]
},
{
"finding":"03 23 4242",
"redactedFinding":"????????42",
"detector":{
"name":"DATE_OF_BIRTH",
"uuid":"540856cb-99cb-42e7-b8aa-cd4f22f019d7"
},
"confidence":"LIKELY",
"location":{
"byteRange":{
"start":20,
"end":30
},
"codepointRange":{
"start":20,
"end":30
},
"rowRange":null,
"columnRange":null,
"commitHash":""
},
"redactedLocation":{
"byteRange":{
"start":20,
"end":30
},
"codepointRange":{
"start":20,
"end":30
},
"rowRange":null,
"columnRange":null,
"commitHash":""
},
"matchedDetectionRuleUUIDs":[
],
"matchedDetectionRules":[
"cc"
]
}
]
],
"redactedPayload":[
"my ssn is *REDACTED* and date of birth is ??/??/??95 and my credit card number is [CREDIT_CARD_NUMBER] and my email is X8QL0mZGHZ+N47nPEccjsLHf2F/5cFqjF16P6wgYJhy8IaxHipHWMBRAufKR4T8FFkvTuTEanu6ZAA+V8NTkNmTLxHarcWPSVClJ8kjXAPltLuR4I2H4eeT+sWEvUP3ik/BF1KcxRpsYWDQO1bNYk+WReXkWlW72Q7rbWuTGFj2uDFCPS+DUraDh9wNBsMPELFOnh1GSQIKCp9U5GMp/kkpo/0idh83RVHXyjZPT4ReKEST2oG2lQ9UuP5LJy/mHX1VYgd8DwlETn8nkhqJ1T0mGs6kHSh22G6N0ic0PjHnj73RiMnQdPwlLw3qyPmFf6RRLKtFuzmFan8ZGtZhcKA==.",
"my date of birth is [REDACTED BY NIGHTFALL] amex"
]
}You can use the exfiltration APIs to search exfiltration events, fetch exfiltration events and also event details. Additionally, you can also view details of the user (actor) whose actions triggered an event, and details of the asset that triggered an event.
You can start scanning for sensitive data in just a few minutes. Our developer-friendly API and comprehensive documentation make it easy to integrate Firewall for AI into your application. Follow our Quickstart guide at this link for step-by-step instructions on setting up the API, configuring detectors, and making your first API call.
The service ingests a local file, scans it for sensitive data with Nightfall, and displays the results in a simple table UI.
We'll deploy the server on Render (a PaaS Heroku alternative) so that you can serve your application publicly in production instead of running it off your local machine. You'll build familiarity with the following tools and frameworks: Python, Flask, Nightfall, Ngrok, Jinja, Render.
Before we get started on our implementation, start by familiarizing yourself with how scanning files works with Nightfall, so you're acquainted with the flow we are implementing.
In a nutshell, file scanning is done asynchronously by Nightfall; after you upload a file to Nightfall and trigger the scan, we perform the scan in the background. When the scan completes, Nightfall delivers the results to you by making a request to your webhook server. This asynchronous behavior allows Nightfall to scan files of varying sizes and complexities without requiring you to hold open a long synchronous request, or continuously poll for updates. The impact of this pattern is that you need a webhook endpoint that can receive inbound notifications from Nightfall when scans are completed - that's what we are building in this tutorial.
You can fork the sample repo and view the complete code here, or follow along below. If you're starting from scratch, create a new GitHub repository.
First, let's start by installing our dependencies. We'll be using Nightfall for data classification, the web framework in Python, and as our web server. Create requirements.txt and add the following to the file:
Then run pip install -r requirements.txt to do the installation.
Next, we'll need our Nightfall API Key and Webhook Signing Secret; the former authenticates us to the Nightfall API, while the latter authenticates that incoming webhooks are originating from Nightfall. You can retrieve your API Key and Webhook Signing Secret from the Nightfall . Complete the Nightfall Quickstart for a more detailed walk-through. for a free Nightfall account if you don't have one.
These values are unique to your account and should be kept safe. This means that we will store them as environment variables and should not store them directly in code or commit them into version control. If these values are ever leaked, be sure to visit the Nightfall Dashboard to re-generate new values for these secrets.
Let's start writing our Flask server. Create a file called app.py. We'll start by importing our dependencies and initializing the Flask and Nightfall clients:
Next, we'll add our first route, which will display "Hello World" when the client navigates to /ping simply as a way to validate things are working:
Run gunicorn app:app on the command line to fire up your server, and navigate to your local server in your web browser. You'll see where the web browser is hosted in the Gunicorn logs, typically it will be 127.0.0.1:8000 aka localhost:8000.
To expose our local webhook server via a public tunnel that Nightfall can send requests to, we'll use ngrok. Download and install ngrok via their quickstart documentation . We'll create an ngrok tunnel as follows:
After running this command, ngrok will create a tunnel on the public internet that redirects traffic from their site to your local machine. Copy the HTTPS tunnel endpoint that ngrok has created: we can use this as the webhook URL when we trigger a file scan.
Let's set this HTTPS endpoint as a local environment variable so we can reference it later:
Tip: With a Pro ngrok account, you can create a subdomain so that your tunnel URL is consistent, instead of randomly generated each time you start the tunnel.
Before you send a file scan request to Nightfall, let's add logic for our incoming webhook endpoint, so that when Nightfall finishes scanning a file, it can successfully send the sensitive findings to us.
First, what does it mean to have findings? If a file has findings, this means that Nightfall identified sensitive data in the file that matched the detection rules you configured. For example, if you told Nightfall to look for credit card numbers, any substring from the request payload that matched our credit card detector would constitute sensitive findings.
We'll host our incoming webhook at /ingest with a POST method.
Nightfall will POST to the webhook endpoint, and in the inbound payload, Nightfall will indicate if there are sensitive findings in the file, and provide a link where we can access the sensitive findings as JSON.
Restart your server so the changes propagate. We'll take a look at the console output of our webhook endpoint and explain what it means in the next section.
Now, we want to trigger a file scan request, so that Nightfall will scan the file and send a POST request to our /ingest webhook endpoint when the scan is complete. We'll write a simple script that sends a file to Nightfall to scan it for . Create a new file called scan.py.
First, we'll establish our dependencies, initialize the Nightfall client, and specify the filepath to the file we wish to scan as well as the webhook endpoint we created above. The filepath is a relative path to any file, in this case we are scanning the sample-pci-xs.csv file which is in the same directory as scan.py. This is a sample CSV file with 10 credit card numbers in it - you can download it in the tutorial's GitHub .
Next, we will initiate the scan request to Nightfall, by specifying our filepath, webhook URL where the scan results should be posted, and our Detection Rule that specifies what sensitive data we are looking for.
In this simple example, we have specified an inline Detection Rule that detects Likely Credit Card Numbers. This Detection Rule is a simple starting point that just scratches the surface of the types of detection you can build with Nightfall. Learn more about building inline detection rules here or how to configure them in the Nightfall .
The scan_id is useful for identifying your scan results later.
Let's run scan.py to trigger our file scan job.
Once Nightfall has finished scanning the file, we'll see our Flask server receive the request at our webhook endpoint (/ingest). In our code above, we parse the webhook payload, and print the following when there are sensitive findings:
In our output, we are printing two URLs.
The first URL is provided to us by Nightfall. It is the temporary signed S3 URL that we can access to fetch the sensitive findings that Nightfall detected.
The second URL won't work yet, we'll implement it next. This URL a we constructed in our ingest() method above - the URL calls /view and passes the Findings URL above as a URL-escaped query parameter.
Let's add a method to our Flask server that opens this URL and displays the findings in a formatted table so that the results are easier to view than downloading them as JSON.
We'll do this by adding a view method that responds to GET requests to the /view route. The /view route will read the URL to the S3 Findings URL via a query parameter. It will then open the findings URL, parse it as JSON, pass the results to an HTML template, and display the results in a simple HTML table using . Jinja is a simple templating engine in Python.
Add the following to our Flask server in app.py:
To display the findings in an HTML table, we'll create a new Flask template. Create a folder in your project directory called templates and add a new file within it called view.html.
Our template uses Jinja to iterate through our findings, and create a table row for each sensitive finding.
Now, if we restart our Flask server, trigger a file scan request, and navigate to the "View" URL printed in the server logs, we should see a formatted table with our results! In fact, we can input any Nightfall-provided signed S3 URL (after URL-escaping it) in the findings_url parameter of the /view route to view it.
As a longtime Heroku user, I was initially inclined to write this tutorial with instructions to deploy our app on Heroku. However, new PaaS vendors have been emerging and I was curious to try them out and see how they compare to Heroku. One such vendor is Render, which is where we'll deploy our app.
Deploying our service on Render is straightforward. If you're familiar with Heroku, the process is quite similar. Once you've signed up or logged into Render (free), we'll do the following:
Create a new Web Service on Render, and permit Render to access your new repo.
Use the following values during creation:
Environment: Python
Build Command: pip install -r requirements.txt
Start Command: gunicorn app:app
Let's also set our environment variables during creation. These are the same values we set locally.
Once Render has finished deploying, you'll get the base URL of your application. Set this as your NIGHTFALL_SERVER_URL locally and re-run scan.py - this time, the file scan request is served by your production Flask server running on Render!
To confirm this, navigate to the Logs tab in your Render app console, you'll see the webhook's output of your file scan results:
Navigate to the View link above in your browser to verify that you can see the results formatted in a table on your production site.
Congrats, you've successfully created a file scanning server and deployed it in production! You're now ready to build more advanced business logic around your file scanner. Here are some ideas on how to extend this tutorial:
Use WebSockets to send a notification back from the webhook to the client that initiated the file scan request
Build a more advanced detection rule using pre-built or custom detectors
Add a user interface to add more interactive capabilities, for example allowing users to upload files or read files from URLs
nightfall
Flask
Gunicornexport NIGHTFALL_API_KEY=<your_key_here>
export NIGHTFALL_SIGNING_SECRET=<your_secret_here>import os
from flask import Flask, request, render_template
from nightfall import Confidence, DetectionRule, Detector, RedactionConfig, MaskConfig, Nightfall
from datetime import datetime, timedelta
import urllib.request, urllib.parse, json
app = Flask(__name__)
nightfall = Nightfall(
key=os.getenv('NIGHTFALL_API_KEY'),
signing_secret=os.getenv('NIGHTFALL_SIGNING_SECRET')
)@app.route("/ping")
def ping():
return "Hello World", 200[2021-11-26 14:22:53 -0800] [61196] [INFO] Starting gunicorn 20.1.0
[2021-11-26 14:22:53 -0800] [61196] [INFO] Listening at: http://127.0.0.1:8000 (61196)
[2021-11-26 14:22:53 -0800] [61196] [INFO] Using worker: sync
[2021-11-26 14:22:53 -0800] [61246] [INFO] Booting worker with pid: 61246Account Nightfall Example
Version 2.3.40
Region United States (us)
Web Interface http://127.0.0.1:4040
Forwarding http://3ecedafba368.ngrok.io -> http://localhost:8000
Forwarding https://3ecedafba368.ngrok.io -> http://localhost:8000export NIGHTFALL_SERVER_URL=https://3ecedafba368.ngrok.io# respond to POST requests at /ingest
# Nightfall will send requests to this webhook endpoint with file scan results
@app.route("/ingest", methods=['POST'])
def ingest():
data = request.get_json(silent=True)
# validate webhook URL with challenge response
challenge = data.get("challenge")
if challenge:
return challenge
# challenge was passed, now validate the webhook payload
else:
# get details of the inbound webhook request for validation
request_signature = request.headers.get('X-Nightfall-Signature')
request_timestamp = request.headers.get('X-Nightfall-Timestamp')
request_data = request.get_data(as_text=True)
if nightfall.validate_webhook(request_signature, request_timestamp, request_data):
# check if any sensitive findings were found in the file, return if not
if not data["findingsPresent"]:
print("No sensitive data present!")
return "", 200
# there are sensitive findings in the file
# URL escape the temporary signed S3 URL where findings are available for download
escaped_url = urllib.parse.quote(data['findingsURL'])
# print the download URL and the URL where we can view the results in our web app
print(f"Sensitive data present. Findings available until {data['validUntil']}.\n\nDownload:\n{data['findingsURL']}\n\nView:\n{request.url_root}view?findings_url={escaped_url}\n")
return "", 200
else:
return "Invalid webhook", 500import os
from nightfall import Confidence, DetectionRule, Detector, RedactionConfig, MaskConfig, Nightfall
nightfall = Nightfall() # reads API key from NIGHTFALL_API_KEY environment variable by default
filepath = "sample-pci-xs.csv" # sample file with sensitive data
webhook_url = f"{os.getenv('NIGHTFALL_SERVER_URL')}/ingest"scan_id, message = nightfall.scan_file(filepath,
webhook_url=webhook_url,
detection_rules=[ DetectionRule([
Detector(
min_confidence=Confidence.LIKELY,
nightfall_detector="CREDIT_CARD_NUMBER",
display_name="Credit Card Number"
)])
])
print(scan_id, message)Sensitive data present. Findings available until 2021-11-28T00:29:00.479700877Z.
Download:
https://files.nightfall.ai/d2160270-6b07-4304-b1ee-e7b98498be82.json?Expires=1638059340&Signature=AjSdNGlXWGXO0QGSi-lOoDBtbhJdLPE7IWXA7IaBCfLr~3X2IcZ1vavHF5iaEDaoZ-3etnZA4Nu8K8Dq8Kd81ShuX6Ze1o87mzb~8lD6WBk8hXShgW-TPBPpLMoBx2sA9TnefTqy94gI4ykt4tt1MttB67Cj69Miw-46cpFkgY9tannNPOF-90b3vlcS44PwqDUGrtTpQiN6WdsTT6LbpN1N92KbPJIRj3PkGwQW7VvpfM8L4wKmyVmVnRO3ixaW-mXXiOWk9rmfHP9UFMYnk99yaGHp4dZ1JfJiClci~Z8dBx288CrvXVjGUCXBJbdlwo6UrKQJCEk9i9vSbCpI2Q__&Key-Pair-Id=K24YOPZ1EKX0YC
View:
https://d3vwatchtower.ngrok.io/ingest/view?findings_url=https%3A//files.nightfall.ai/d2160270-6b07-4304-b1ee-e7b98498be82.json%3FExpires%3D1638059340%26Signature%3DAjSdNGlXWGXO0QGSi-lOoDBtbhJdLPE7IWXA7IaBCfLr~3X2IcZ1vavHF5iaEDaoZ-3etnZA4Nu8K8Dq8Kd81ShuX6Ze1o87mzb~8lD6WBk8hXShgW-TPBPpLMoBx2sA9TnefTqy94gI4ykt4tt1MttB67Cj69Miw-46cpFkgY9tannNPOF-90b3vlcS44PwqDUGrtTpQiN6WdsTT6LbpN1N92KbPJIRj3PkGwQW7VvpfM8L4wKmyVmVnRO3ixaW-mXXiOWk9rmfHP9UFMYnk99yaGHp4dZ1JfJiClci~Z8dBx288CrvXVjGUCXBJbdlwo6UrKQJCEk9i9vSbCpI2Q__%26Key-Pair-Id%3DK24YOPZ1EKX0YC# respond to GET requests at /view
# Users can access this page to view their file scan results in a table
@app.route("/view")
def view():
# get the findings URL from the query parameters
findings_url = request.args.get('findings_url')
if findings_url:
# download the findings from the findings URL and parse them as JSON
with urllib.request.urlopen(findings_url) as url:
data = json.loads(url.read().decode())
# render the view.html template and provide the findings object to display in the template
return render_template('view.html', findings=data['findings'])<!DOCTYPE HTML>
<html>
<head>
<title>File Scan Viewer</title>
<style>
table, th, td {
border: 1px solid black;
}
table {
width: 100%;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<th>Detector</th>
<th>beforeContext</th>
<th>Finding</th>
<th>afterContext</th>
<th>byteRangeStart</th>
<th>byteRangeEnd</th>
<th>Confidence</th>
</tr>
</thead>
<tbody>
{% for finding in findings %}
<tr>
<td>{{ finding['detector']['name'] }}</td>
<td>{{ finding['beforeContext'] }}</td>
<td>{{ finding['finding'] }}</td>
<td>{{ finding['afterContext'] }}</td>
<td>{{ finding['location']['byteRange']['start'] }}</td>
<td>{{ finding['location']['byteRange']['start'] }}</td>
<td>{{ finding['confidence'] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>NIGHTFALL_API_KEY
NIGHTFALL_SIGNING_SECRETexport NIGHTFALL_SERVER_URL=https://your-app-url.onrender.com
python3 scan.pyNov 26 04:29:06 PM Sensitive data present. Findings available until 2021-11-28T00:28:24.564972786Z.
Nov 26 04:29:06 PM
Nov 26 04:29:06 PM Download:
Nov 26 04:29:06 PM https://files.nightfall.ai/d6b6ee4f-d1a8-4fb6-b35a-cb6f88d58083.json?Expires=1638059304&Signature=hz1TN5UXjCGTxCxq~jT2wfuUWlj9Se-mWNL1K-tJhiAIXUg1FxJrCVP2iH1I4TNymFBuOnj5TTiLGpD8tZAKGm9J0lTHncZkaeaU8KZQ2j-~8qYQVlunNj019sqtTkMbVRfakzYzW-qWHEvLXN-PFcGYX05g3LZHvW802-lAVlM-WpGApw2u8BnzoY1pdWAxpJ0VIN1Zax4UuVeQBKieR7k8H9v9HdYYJlVGkVA5F9EzklLy99fyD8r4WR~jfqN5Fr1KceDtsxffC6MPuZ8nIIdSG5~tVtjCjgIjyh3IePPW1Wq-E8yZiVAhpDDbYX1wngUTwlAu~MU7N39vd8mlYQ__&Key-Pair-Id=K24YOPZ1EKX0YC
Nov 26 04:29:06 PM
Nov 26 04:29:06 PM View:
Nov 26 04:29:06 PM https://flask-file-scanner-example.onrender.com/view?findings_url=https%3A//files.nightfall.ai/d6b6ee4f-d1a8-4fb6-b35a-cb6f88d58083.json%3FExpires%3D1638059304%26Signature%3Dhz1TN5UXjCGTxCxq~jT2wfuUWlj9Se-mWNL1K-tJhiAIXUg1FxJrCVP2iH1I4TNymFBuOnj5TTiLGpD8tZAKGm9J0lTHncZkaeaU8KZQ2j-~8qYQVlunNj019sqtTkMbVRfakzYzW-qWHEvLXN-PFcGYX05g3LZHvW802-lAVlM-WpGApw2u8BnzoY1pdWAxpJ0VIN1Zax4UuVeQBKieR7k8H9v9HdYYJlVGkVA5F9EzklLy99fyD8r4WR~jfqN5Fr1KceDtsxffC6MPuZ8nIIdSG5~tVtjCjgIjyh3IePPW1Wq-E8yZiVAhpDDbYX1wngUTwlAu~MU7N39vd8mlYQ__%26Key-Pair-Id%3DK24YOPZ1EKX0YCThe Nightfall MCP server provides 33 tools organized into seven categories.
Every tool the server advertises carries the standard MCP annotations, so an agent harness can decide what to run unattended and what to confirm with a person first. All four fields are always present — none is left to its default.
readOnlyHint
The tool does not modify anything. True for all 26 read tools.
Tools fall into exactly three profiles:
Remediation tools are open-world because the action executes in Google Drive, Slack, GitHub, Jira or Teams, and non-idempotent because a repeated call sends another notification or files another ticket. Policy-scope tools stay inside Nightfall, but count as destructive because a call can remove entries from a policy's scope, which silently ends DLP coverage for those users or domains. They are idempotent: the payload is a target state, not a delta, so retrying a call that timed out is safe.
Work with Data Loss Prevention policy violations detected across your integrations.
Investigate data exfiltration attempts and suspicious file activity.
Monitor configuration risks and permission changes.
Track user and asset activity across all event types.
Adjust which users and domains a policy applies to. Only supported for Google Drive policies.
Inventory of AI tooling discovered across managed endpoints: MCP servers, agent plugins, agent hooks and IDE extensions.
SaaS and AI application usage discovered across the tenant.
Seven of the 33 tools change state. Each is annotated readOnlyHint: false and destructiveHint: true, and a harness that honours annotations will ask before running them. The other 26 only read.
This section provides a comprehensive reference of searchable fields across different event types. Use these when constructing advanced queries.
Core Fields
state: ACTIVE, PENDING, RESOLVED, EXPIRED
integration_name: github, gdrive, slack, confluence, jira, salesforce, teams, onedrive, etc.
risk_label: HIGH, MEDIUM, LOW
Integration-Specific Fields
Slack
slack.channel_name, slack.channel_id, slack.workspace
GitHub
github.org, github.repository, github.repository_owner, github.branch, github.commit, github.author_email
Google Drive
gdrive.drive
Confluence
confluence.space_name, confluence.parent_page_name
Jira
jira.project_name, jira.ticket_number
Salesforce
salesforce.org_name, salesforce.object, salesforce.record_id
Microsoft Teams
teams.team_name, teams.channel_name, teams.channel_type, teams.team_sensitivity, teams.sender, teams.msg_importance, teams.msg_attachment, teams.chat_id, teams.chat_type, teams.chat_topic
OneDrive
onedrive.drive_owner, onedrive.drive_owner_email, onedrive.file_name, onedrive.created_by, onedrive.created_by_email, onedrive.modified_by, onedrive.modified_by_email
Zendesk
zendesk.ticket_status, zendesk.ticket_title, zendesk.ticket_group_assignee, zendesk.current_user_role
Notion
notion.created_by, notion.last_edited_by, notion.page_title, notion.workspace_name
Gmail
gmail.user_name, gmail.from, gmail.to, gmail.cc, gmail.bcc, gmail.thread_id, gmail.subject, gmail.attachment_name, gmail.attachment_type
Core Fields
event_type: file_download, file_upload, permission_change, etc.
state: ACTIVE, PENDING, RESOLVED, EXPIRED
last_actioned_by: NIGHTFALL, ADMIN, END_USER
Actor Fields
actor_name, actor_email
user_name, user_email (backward compatible aliases)
Resource Fields
resource_id, resource_name, resource_owner_name, resource_owner_email, resource_content_type, notes
Endpoint Fields
endpoint.device_id, endpoint.machine_name
Google Drive
gdrive.permission, gdrive.shared_internal_email, gdrive.shared_external_email, gdrive.drive, gdrive.file_owner, gdrive.label_name
Salesforce
salesforce.report.scope, salesforce.report.event_source, salesforce.report.source_ip, salesforce.report.session_level, salesforce.report.operation, salesforce.report.description
salesforce.file.source_ip, salesforce.file.session_level
Security posture events support the same query fields as exfiltration events.
AND: Combine multiple conditions (both must match)
OR: Alternative conditions (either can match)
field:value syntax for exact matches
Example:
Find violations by user and integration:
Search across multiple users:
Filter by channel and state:
Time-based queries:
The MCP server returns structured errors in tool responses:
HTTP-level errors from the API gateway:
Tools that return lists support cursor-based pagination. When more results are available, the response includes a nextPageToken field. Pass this value as pageToken in your next request to fetch the next page.
Simply ask: "Show me the next page of results"
The AI client handles this automatically when you ask for more results.
MCP requests share the same rate limits and quotas as the Nightfall REST API. If you receive a 429 response, wait for the duration indicated in the Retry-After header before retrying.
user_email, user_name: Filter by specific users
last_actioned_by: NIGHTFALL, ADMIN, END_USER
confidence: Detection confidence level
policy_id, detection_rule_id, detector_id: Policy and rule identifiers
teams.chat_participantdestructiveHint
The tool may make changes that Nightfall cannot undo.
idempotentHint
Repeating the call with identical arguments has no further effect.
openWorldHint
The effect lands in a connected third-party system rather than in Nightfall alone.
Read
26
true
search_violations
Search violations using structured queries (field:value syntax)
Read-only
list_violations
Browse recent violations with date range filters
search_exfiltration_events
Search exfiltration events with advanced filters
Read-only
list_exfiltration_events
Browse recent exfiltration events
search_posture_events
Search for security posture issues
Read-only
list_posture_events
Browse recent posture events
get_actor_activity
Get complete user activity history
Read-only
get_asset_activity
Track file/document activity history
update_policy_user_scope
Add or remove users in a DLP policy's user scope, by email
Destructive
update_policy_domain_scope
Add or remove domains in a DLP policy's domain scope
list_ai_inventory
List any AI inventory — set type to mcp_server, plugin, hook or ide_extension, and scope to company or device
Read-only
list_mcp_servers
Browse discovered MCP servers with device counts, usage and risk
app_intelligence_list_apps
List discovered applications, with filtering and sorting
Read-only
app_intelligence_get_app_details
Get details for one application
take_action_on_violations
Remediates in the connected SaaS tenant — including HARD_DELETE, DELETE_FILE, REVOKE_ACCESS and SUSPEND_ACCOUNT
take_action_on_exfiltration_events
Remediates exfiltration events — access control and notification actions
take_action_on_posture_events
integration_name:github AND risk_label:HIGH AND state:ACTIVEuser_email:jane@example.com AND integration_name:slackuser_email:jane@example.com OR user_email:john@example.comslack.channel_name:general AND state:PENDINGcreatedAfter=<unix_timestamp> AND risk_label:HIGHUNAUTHORIZED
Missing or invalid API key
INVALID_INPUT
Malformed parameters or invalid values
NOT_FOUND
401 Unauthorized
Invalid or missing API key
429 Too Many Requests
Rate limit or quota exceeded—check Retry-After header
Annotations are advisory metadata for the calling harness, not an access control. The server does not scope tools per key: any enabled API key can call all 33 tools, including the seven that modify data. Your key determines which tenant's data is reachable, not which tools may be used.
So the annotations are what a well-behaved harness uses to decide when to ask a person first — they are not what stops an unauthorized call. Control access by controlling who holds the key, and by running a harness that honours the hints.
Removing an entry from a policy's scope ends DLP coverage for it. These tools take an add and a delete payload in one call and return the full resulting include and exclude lists, so the response is the place to confirm what the policy now covers.
false
true
false
Remediation
3 × take_action_*
false
true
false
true
Policy scope
4 × update_policy_*
false
true
true
false
Read-only
get_violation
Get full details for a specific violation
Read-only
get_violation_findings
View sensitive data findings within a violation
Read-only
get_violation_activity
Review activity timeline and remediation history
Read-only
take_action_on_violations
Execute remediation actions (resolve, block, delete, etc.)
Destructive
Read-only
get_exfiltration_event
Get complete event details and affected assets
Read-only
get_exfiltration_event_activity
View event timeline and status changes
Read-only
take_action_on_exfiltration_events
Execute remediation actions on exfiltration events
Destructive
Read-only
get_posture_event
Get detailed event information
Read-only
get_posture_event_activity
View event activity history
Read-only
take_action_on_posture_events
Execute remediation actions on posture events
Destructive
Read-only
Destructive
update_policy_trigger_user_scope
Add or remove trigger-scoped users on a posture management policy
Destructive
update_policy_trigger_domain_scope
Add or remove trigger-scoped domains on a posture management policy
Destructive
Read-only
get_mcp_server
Get one MCP server, including public registry metadata when matched
Read-only
list_mcp_server_devices
List the devices using a given MCP server, with a per-client breakdown
Read-only
list_mcp_devices
List devices that have any MCP server installed
Read-only
get_device_mcp_servers
Get one device and every MCP server running on it
Read-only
Read-only
app_intelligence_get_app_destinations
Get the destinations an application sends data to
Read-only
app_intelligence_get_summary_stats
Summary statistics for a date range (fromDate and toDate, both required, Unix seconds)
Read-only
app_intelligence_list_categories
List available application categories
Read-only
Remediates posture events — access control and notification actions
update_policy_user_scope
Adds or removes users from a DLP policy's scope
update_policy_domain_scope
Adds or removes domains from a DLP policy's scope
update_policy_trigger_user_scope
Adds or removes users from a posture policy's trigger scope
update_policy_trigger_domain_scope
Adds or removes domains from a posture policy's trigger scope
The requested violation or event does not exist
SERVICE_ERROR
Backend service failure—retry after a moment
INTERNAL_ERROR
Unexpected system error
Endpoint data loss prevention (DLP) discovers, classifies, and protects sensitive data - like PII, credit card numbers, and secrets - that proliferates onto endpoint devices, like your computer or EC2 machines. This is a way to help keep data safe, so that you can detect and stop occurrences of data exfiltration. Our endpoint DLP application will be composed of two core services that will run locally. The first service will monitor for file system events using the Watchdog package in Python. When a file system event is triggered, such as when a file is created or modified, the service will send the file to Nightfall to be scanned for sensitive data. The second service is a webhook server that will receive scan results from Nightfall, parse the sensitive findings, and write them to a CSV file as output. You'll build familiarity with the following tools and frameworks:
Python
Flask
Nightfall
Ngrok
Watchdog
Before we get started on our implementation, start by familiarizing yourself with with Nightfall, so you're acquainted with the flow we are implementing.
In a nutshell, file scanning is done asynchronously by Nightfall; after you upload a file to Nightfall and trigger the scan, we perform the scan in the background. When the scan completes, Nightfall delivers the results to you by requesting your webhook server. This asynchronous behavior allows Nightfall to scan files of varying sizes and complexities without requiring you to hold open a long synchronous request, or continuously poll for updates. The impact of this pattern is that you need a webhook endpoint that can receive inbound notifications from Nightfall when scans are completed - that's one of the two services we are building in this tutorial.
You can fork the sample repo and view the complete code , or follow along below. If you're starting from scratch, create a new GitHub repository. This tutorial was developed on a Mac and assumes that's the endpoint operating system you're running, however, this tutorial should work across operating systems with minor modifications. For example, you may wish to extend this tutorial by running endpoint DLP on an EC2 machine to monitor your production systems.
First, let's start by installing our dependencies. We'll be using Nightfall for data classification, the web framework in Python, for monitoring file system events, and as our web server. Create requirements.txt and add the following to the file:
Then run pip install -r requirements.txt to do the installation.
Next, we'll need our Nightfall API Key and Webhook Signing Secret; the former authenticates us to the Nightfall API, while the latter authenticates that incoming webhooks are originating from Nightfall. You can retrieve your API Key and Webhook Signing Secret from the Nightfall . Complete the Nightfall Quickstart for a more detailed walk-through. for a free Nightfall account if you don't have one.
These values are unique to your account and should be kept safe. This means that we will store them as environment variables and should not store them directly in code or commit them into version control. If these values are ever leaked, be sure to visit the Nightfall Dashboard to re-generate new values for these secrets.
Watchdog is a Python module that watches for file system events. Create a file called scanner.py. We'll start by importing our dependencies and setting up a basic event handler. This event handler responds to file change events for file paths that match a given set of regular expressions (regexes). In this case, the .* indicates we are matching on any file path - we'll customize this a bit later. When a file system event is triggered, we'll print a line to the console.
Run python scanner.py and you'll notice lots of lines getting printed to the console. These are all the files that are getting created and changed on your machine in real-time. You'll notice that your operating system and the apps you're running are constantly writing, modifying, and deleting files on disk!
Next, we'll update our event handler so that instead of simply printing to the console, we are sending the file to Nightfall to be scanned. We will initiate the scan request to Nightfall, by specifying the file path of the changed/created file, a webhook URL where the scan results should be sent, and our Detection Rule that specifies what sensitive data we are looking for. If the file scan is initiated successfully, we'll print the corresponding Upload ID that Nightfall provides us to the console. This ID will be useful later when identifying scan results.
Here's our complete scanner.py, explained further below:
We can't run this just yet, since we need to set our webhook URL, which is currently reading from an environment variable that we haven't set yet. We'll create our webhook server and set the webhook URL in the next set of steps.
In this example, we have specified an inline Detection Rule that detects Likely Credit Card Numbers, Social Security Numbers, and API Keys. This Detection Rule is a simple starting point that just scratches the surface of the types of detection you can build with Nightfall. Learn more about building inline detection rules here or how to configure them in the Nightfall .
Also note that we've updated our regex from .* to a set of file paths on Macs that commonly contain user generated files - the Desktop, Documents, and Downloads folders:
You can customize these regexes to whatever file paths are of interest to you. Another option is to write a catch-all regex that ignores/excludes paths to config and temp files:
Next, we'll set up our Flask webhook server, so we can receive file scanning results from Nightfall. Create a file called app.py. We'll start by importing our dependencies and initializing the Flask and Nightfall clients:
Next, we'll add our first route, which will display "Hello World" when the client navigates to /ping simply as a way to validate things are working:
In a second command line window, run gunicorn app:app on the command line to fire up your server, and navigate to your local server in your web browser. You'll see where the web browser is hosted in the Gunicorn logs, typically it will be 127.0.0.1:8000 aka localhost:8000.
To expose our local webhook server via a public tunnel that Nightfall can send requests to, we'll use ngrok. Download and install ngrok via their quickstart documentation . We'll create an ngrok tunnel as follows:
After running this command, ngrok will create a tunnel on the public internet that redirects traffic from their site to your local machine. Copy the HTTPS tunnel endpoint that ngrok has created: we can use this as the webhook URL when we trigger a file scan.
Let's set this HTTPS endpoint as a local environment variable so we can reference it later:
Before we send a file scan request to Nightfall, let's implement our incoming webhook endpoint, so that when Nightfall finishes scanning a file, it can successfully send the sensitive findings to us.
First, what does it mean to have findings? If a file has findings, this means that Nightfall identified sensitive data in the file that matched the detection rules you configured. For example, if you told Nightfall to look for credit card numbers, any substring from the request payload that matched our credit card detector would constitute sensitive findings.
We'll host our incoming webhook at /ingest with a POST method.
Nightfall will POST to the webhook endpoint, and in the inbound payload, Nightfall will indicate if there are sensitive findings in the file, and provide a link where we can access the sensitive findings as JSON.
We'll validate the inbound webhook from Nightfall, retrieve the JSON findings from the link provided, and write the findings to a CSV file. First, let's initialize our CSV file where we will write results, and add our /ingest POST method.
You'll notice that when there are sensitive findings, we call the output_results() method. Let's write that next. In output_results(), we are going to parse the findings and write them as rows into our CSV file.
Restart your server so the changes propagate. We'll take a look at the console and CSV output of our webhook endpoint in the next section.
In our previous command line window, we can now turn our attention back to scanner.py. We now have our webhook URL so let's set it here as well and run our scanner.
To trigger a file scan event, download the following . Assuming it automatically downloads to your Downloads folder, this should immediately trigger a file change event and you'll see console log output! If not, you can also download the file with curl into a location that matches your event handler's regex we set earlier.
You'll see the following console output from scanner.py:
And the following console output from our webhook server:
And the following sensitive findings written to results.csv:
Each row in the output CSV will correspond to a sensitive finding. Each row will have the following fields, which you can customize in app.py: the upload ID provided by Nightfall, an incrementing index, timestamp, characters before the sensitive finding (for context), the sensitive finding itself, characters after the sensitive finding (for context), the confidence level of the detection, the byte range location (character indicies) of the sensitive finding in its parent file, and the corresponding detection rules that flagged the sensitive finding.
Note that you may also see events for system files like .DS_Store or errors corresponding to failed attempts to scan temporary versions of files. This is because doing things like downloading a file can trigger multiple file modification events. As an extension to this tutorial, you could consider filtering those out further, though they shouldn't impact our ability to scan files of interest.
If we leave these services running, we'll continue to monitor files for sensitive data and appending to our results CSV when sensitive findings are discovered!
We can run both of our services in the background nohup so that we don't need to leave two command line tabs open indefinitely. We'll pipe console output to log files so that we can always reference the application's output or determine if the services crashed for any reason.
This will return the corresponding process IDs - we can always check on these later with the ps command.
This post is simply of a proof of concept version of endpoint DLP. Building a production-grade endpoint DLP application will have additional complexity and functionality. However, the detection engine is one of the biggest components of an endpoint DLP system, and this example should give you a sense of how easy it is to integrate with Nightfall's APIs and the power of Nightfall's detection engine.
Here are few ideas on how you can extend upon this service further:
Run the scanner on EC2 machines to scan your production machines in real-time
Respond to more system events like I/O of USB drives and external ports
Implement remediation actions like end-user notifications or file deletion
Redact the sensitive findings prior to writing them to the results file
Store the results in the cloud for central reporting
Package in an executable so the application can be run easily
Scan all files on disk on the first boot of the application
nightfall
Flask
Gunicorn
watchdogexport NIGHTFALL_API_KEY=<your_key_here>
export NIGHTFALL_SIGNING_SECRET=<your_secret_here>import os
import time
from watchdog.observers import Observer
from watchdog.events import RegexMatchingEventHandler
from nightfall import Confidence, DetectionRule, Detector, RedactionConfig, MaskConfig, Nightfall
class MyHandler(RegexMatchingEventHandler):
# event handler callback that is called when a file is modified (created or changed)
def on_modified(self, event):
print(f'Event type: {event.event_type} | Path: {event.src_path}')
if __name__ == "__main__":
regexes = [ ".*" ]
# register event handler to monitor file paths that match our regex
event_handler = MyHandler(regexes)
observer = Observer()
observer.schedule(event_handler, path='', recursive=True)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()Event type: modified | Path: /Users/myuser/Library/Caches
Event type: modified | Path: /Users/myuser/Library/Caches/com.apple.nsservicescache.plist
Event type: modified | Path: /Users/myuser/Library/Caches
Event type: modified | Path: /Users/myuser/Library/Caches/Google/Chrome/Default/Cache
Event type: modified | Path: /private/tmp
Event type: modified | Path: /Users/myuser/Library/Preferences/ContextStoreAgent.plist
Event type: modified | Path: /private/tmp
Event type: modified | Path: /Users/myuser/Library/Assistant
Event type: modified | Path: /Users/myuser/Library/Assistant/SyncSnapshot.plist
...import os
import time
from watchdog.observers import Observer
from watchdog.events import RegexMatchingEventHandler
from nightfall import Confidence, DetectionRule, Detector, RedactionConfig, MaskConfig, Nightfall
class MyHandler(RegexMatchingEventHandler):
def scan_file(self, filepath):
nightfall = Nightfall() # reads API key from NIGHTFALL_API_KEY environment variable by default
webhook_url = f"{os.getenv('NIGHTFALL_SERVER_URL')}/ingest" # webhook server we'll create
try:
scan_id, message = nightfall.scan_file(
filepath,
webhook_url=webhook_url,
# detection rule to detect credit card numbers, SSNs, and API keys
detection_rules=[ DetectionRule([
Detector(
min_confidence=Confidence.LIKELY,
nightfall_detector="CREDIT_CARD_NUMBER",
display_name="Credit Card Number"),
Detector(
min_confidence=Confidence.LIKELY,
nightfall_detector="US_SOCIAL_SECURITY_NUMBER",
display_name="US Social Security Number"),
Detector(
min_confidence=Confidence.LIKELY,
nightfall_detector="API_KEY",
display_name="API Key")
])
])
return scan_id, message
except Exception as err:
print(f"Error processing {filepath} | {err}")
return None, None
def on_modified(self, event):
# scan file with Nightfall
scan_id, message = self.scan_file(event.src_path)
if scan_id:
print(f"Scan initiated | Path {event.src_path} | UploadID {scan_id}")
print(f'Event type: {event.event_type} | Path: {event.src_path}')
if __name__ == "__main__":
regexes = [ ".*/Downloads/.*", ".*/Desktop/.*", ".*/Documents/.*" ]
# register event handler to monitor file paths that match our regexes
event_handler = MyHandler(regexes)
observer = Observer()
observer.schedule(event_handler, path='', recursive=True)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()regexes = [ ".*/Downloads/.*", ".*/Desktop/.*", ".*/Documents/.*" ]regexes = [ "(?!/opt/|.*/Library/|.*/private/|/System/|/Applications/|/usr/).*" ]import os
from flask import Flask, request, render_template
from nightfall import Confidence, DetectionRule, Detector, RedactionConfig, MaskConfig, Nightfall
from datetime import datetime, timedelta
import urllib.request, urllib.parse, json
import csv
app = Flask(__name__)
nightfall = Nightfall(
key=os.getenv('NIGHTFALL_API_KEY'),
signing_secret=os.getenv('NIGHTFALL_SIGNING_SECRET')
)@app.route("/ping")
def ping():
return "Hello World", 200[2021-11-26 14:22:53 -0800] [61196] [INFO] Starting gunicorn 20.1.0
[2021-11-26 14:22:53 -0800] [61196] [INFO] Listening at: http://127.0.0.1:8000 (61196)
[2021-11-26 14:22:53 -0800] [61196] [INFO] Using worker: sync
[2021-11-26 14:22:53 -0800] [61246] [INFO] Booting worker with pid: 61246./ngrok http 8000Account Nightfall Example
Version 2.3.40
Region United States (us)
Web Interface http://127.0.0.1:4040
Forwarding http://3ecedafba368.ngrok.io -> http://localhost:8000
Forwarding https://3ecedafba368.ngrok.io -> http://localhost:8000export NIGHTFALL_SERVER_URL=https://3ecedafba368.ngrok.io# create CSV where sensitive findings will be written
headers = ["upload_id", "#", "datetime", "before_context", "finding", "after_context", "detector", "confidence", "loc", "detection_rules"]
with open(f"results.csv", 'a') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(headers)
# respond to POST requests at /ingest
# Nightfall will send requests to this webhook endpoint with file scan results
@app.route("/ingest", methods=['POST'])
def ingest():
data = request.get_json(silent=True)
# validate webhook URL with challenge response
challenge = data.get("challenge")
if challenge:
return challenge
# challenge was passed, now validate the webhook payload
else:
# get details of the inbound webhook request for validation
request_signature = request.headers.get('X-Nightfall-Signature')
request_timestamp = request.headers.get('X-Nightfall-Timestamp')
request_data = request.get_data(as_text=True)
if nightfall.validate_webhook(request_signature, request_timestamp, request_data):
# check if any sensitive findings were found in the file, return if not
if not data["findingsPresent"]:
print("No sensitive data present!")
return "", 200
# there are sensitive findings in the file
output_results(data)
return "", 200
else:
return "Invalid webhook", 500def output_results(data):
findings_url = data['findingsURL']
# open findings URL provided by Nightfall to access findings
with urllib.request.urlopen(findings_url) as url:
findings = json.loads(url.read().decode())
findings = findings['findings']
print(f"Sensitive data found, outputting {len(findings)} finding(s) to CSV | UploadID {data['uploadID']}")
table = []
# loop through findings JSON, get relevant finding metadata, write each finding as a row into output CSV
for i, finding in enumerate(findings):
row = [
data['uploadID'],
i+1,
datetime.now(),
repr(finding['beforeContext']),
repr(finding['finding']),
repr(finding['afterContext']),
finding['detector']['name'],
finding['confidence'],
finding['location']['byteRange'],
finding['matchedDetectionRules']
]
table.append(row)
with open(f"results.csv", 'a') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(row)
returnexport NIGHTFALL_SERVER_URL=https://3ecedafba368.ngrok.io
python scanner.pycurl https://raw.githubusercontent.com/nightfallai/dlp-sample-data/main/sample-pci.csv > ~/Downloads/sample-pci.csvEvent type: modified | Path: /Users/myuser/Downloads/sample-pci.csv
Scan initiated | Path /Users/myuser/Downloads/sample-pci.csv | UploadID c23fdde2-5e98-4183-90b0-31e2cdd20ac0Sensitive data found, outputting 10 finding(s) to CSV | UploadID ac6a4a9d-a7b9-4a78-810d-8a66f7644704upload_id,#,datetime,before_context,finding,after_context,detector,confidence,loc,detection_rules
ac6a4a9d-a7b9-4a78-810d-8a66f7644704,1,2021-12-04 22:12:21.039602,'Name\tCredit Card\nRep. Viviana Hintz\t','5433-9502-3725-7862','\nEloisa Champlin\t3457-389808-83234\nOmega',Credit Card Number,VERY_LIKELY,"{'start': 36, 'end': 55}",[]
...nohup python -u scanner.py > scanner.log &
nohup gunicorn app:app > server.log &The Nightfall MCP (Model Context Protocol) server enables AI assistants like Claude, ChatGPT, and Cursor to interact directly with your Nightfall security data. Instead of navigating dashboards or running API queries manually, you can use natural language to investigate violations, search for exfiltration events, review security posture, and take remediation actions.
Natural Language Interface: Ask questions in plain English instead of learning complex query syntax
Faster Investigations: Get instant answers to security questions without switching between tools
Workflow Integration: Access Nightfall data directly in your development and collaboration environments
Automated Analysis: Let AI help you identify patterns, summarize findings, and recommend actions
Before connecting to the Nightfall MCP server, ensure you have:
An active Nightfall subscription with appropriate permissions
A Nightfall API key from the Developer Platform
An MCP-compatible AI client (Claude Desktop, Cursor, Windsurf, or custom)
Log in to the Nightfall Dashboard at https://app.nightfall.ai
Go to Developer Platform > API Keys in the dashboard.
Click Generate New Key and provide a descriptive name (e.g., "Claude MCP Integration").
The Nightfall MCP server supports any MCP-compatible client. Below are configuration examples for popular AI tools.
Add the following configuration to your Claude Desktop config file:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
Replace YOUR_NIGHTFALL_API_KEY with your actual API key, then restart Claude Desktop.
Open Cursor Settings > MCP and add:
Add to ~/.codeium/windsurf/mcp_config.json:
For custom MCP clients, connect using Streamable HTTP transport:
The server operates in stateless mode and returns application/json responses.
The Nightfall MCP server provides 16 specialized tools organized into four categories.
Work with Data Loss Prevention policy violations detected across your integrations.
Investigate data exfiltration attempts and suspicious file activity.
Monitor configuration risks and permission changes.
Track user and asset activity across all event types.
Here are real-world scenarios where the Nightfall MCP server delivers immediate value.
Example: "Show me all active high-risk violations from GitHub in the last week"
The AI automatically uses search_violations with appropriate filters and returns results in seconds. You can then ask follow-up questions like "Which repository has the most violations?" or "Show me the sensitive data found in violation abc-123" without manually constructing queries.
Example: "What has user jane@example.com been doing in the last 30 days?"
Get a complete timeline of user activity including file downloads, permission changes, and policy violations. The AI summarizes patterns and flags anomalies automatically.
Example: "Resolve all pending Slack violations from the #general channel"
Instead of manually processing violations one by one, describe the action in natural language. The AI finds matching violations and executes the appropriate remediation action.
Example: "Generate a summary of all HIPAA violations this quarter grouped by department"
The AI retrieves relevant data, performs grouping and aggregation, and creates a formatted report—all from a single request.
Example: "Are there any exfiltration events involving bulk downloads from Google Drive?"
Quickly identify potential data theft attempts by searching for specific event patterns across your cloud storage integrations.
Example: "List all posture events with permission changes this month"
Monitor access control changes across your environment to identify security configuration drift or policy violations.
These examples demonstrate the flexibility of natural language queries. You don't need to memorize syntax—just describe what you need.
"Show me today's violations"
"List high-risk violations in the last 7 days"
"Find violations in the engineering-team Slack channel"
"What GitHub repositories have violations?"
"Show violations by john@company.com"
"What files has jane@company.com accessed this week?"
"Track user activity for contractor-email@vendor.com"
"Find all Salesforce violations in the Sales org"
"Show Google Drive files shared externally"
"List Confluence pages with public links"
"Check Microsoft Teams for sensitive data sharing"
"Compare violation trends month over month"
"Identify users with the most violations"
"What types of sensitive data are most commonly exposed?"
"Summarize security posture improvements over the last quarter"
"Mark these violations as resolved"
"Block access to this file"
"Delete violations in test channels"
"Quarantine all high-risk violations from last month"
Store API keys in secure credential managers, never in code or configuration files committed to version control
Rotate API keys quarterly or immediately if compromise is suspected
Use dedicated API keys for each integration rather than sharing across systems
Review API key permissions regularly and follow least-privilege principles
Start with broader queries and refine based on results rather than trying to construct perfect queries immediately
Use date ranges to limit result sets when investigating recent incidents
Ask for pagination when dealing with large result sets to avoid overwhelming responses
Combine filters naturally: "high-risk GitHub violations from last week" is more efficient than multiple separate queries
Be specific about time ranges: "last 7 days" is clearer than "recently"
Use exact usernames or email addresses when investigating specific actors
Ask follow-up questions to drill deeper: "Show me the findings" after reviewing a violation
Request summaries for complex data: "Summarize these violations by severity"
Set up dedicated Slack/Teams channels for security alerts and use MCP to investigate directly from your collaboration tool
Create saved prompts for common investigations to maintain consistency across your security team
Document investigation procedures that leverage MCP for faster onboarding of new analysts
Use MCP in conjunction with the Nightfall dashboard for comprehensive security operations
If you encounter issues not covered in this guide:
Email Support: support@nightfall.ai
Documentation: https://help.nightfall.ai
Dashboard: https://app.nightfall.ai
Status Page: https://status.nightfall.ai
We continuously improve the MCP server based on customer feedback. Please share:
Feature requests for new query capabilities
Use cases we should highlight in documentation
Integration challenges or configuration pain points
Success stories of how MCP improves your security operations
Model Context Protocol Specification: https://modelcontextprotocol.io
Nightfall API Documentation: https://help.nightfall.ai/reference
Security Best Practices Guide: Available in Nightfall Dashboard > Resources
Video Tutorials: https://nightfall.ai/resources/videos
This section provides a comprehensive reference of searchable fields across different event types. Use these when constructing advanced queries.
Core Fields
state: ACTIVE, PENDING, RESOLVED, EXPIRED
integration_name: github, gdrive, slack, confluence, jira, salesforce, teams, onedrive, etc.
risk_label: HIGH, MEDIUM, LOW
Integration-Specific Fields
Slack
slack.channel_name, slack.channel_id, slack.workspace
GitHub
github.org, github.repository, github.repository_owner, github.branch, github.commit, github.author_email
Google Drive
gdrive.drive
Confluence
confluence.space_name, confluence.parent_page_name
Jira
jira.project_name, jira.ticket_number
Salesforce
salesforce.org_name, salesforce.object, salesforce.record_id
Microsoft Teams
teams.team_name, teams.channel_name, teams.channel_type, teams.team_sensitivity, teams.sender, teams.msg_importance, teams.msg_attachment, teams.chat_id, teams.chat_type, teams.chat_topic
OneDrive
onedrive.drive_owner, onedrive.drive_owner_email, onedrive.file_name, onedrive.created_by, onedrive.created_by_email, onedrive.modified_by, onedrive.modified_by_email
Zendesk
zendesk.ticket_status, zendesk.ticket_title, zendesk.ticket_group_assignee, zendesk.current_user_role
Notion
notion.created_by, notion.last_edited_by, notion.page_title, notion.workspace_name
Gmail
gmail.user_name, gmail.from, gmail.to, gmail.cc, gmail.bcc, gmail.thread_id, gmail.subject, gmail.attachment_name, gmail.attachment_type
Core Fields
event_type: file_download, file_upload, permission_change, etc.
state: ACTIVE, PENDING, RESOLVED, EXPIRED
last_actioned_by: NIGHTFALL, ADMIN, END_USER
Actor Fields
actor_name, actor_email
user_name, user_email (backward compatible aliases)
Resource Fields
resource_id, resource_name, resource_owner_name, resource_owner_email, resource_content_type, notes
Endpoint Fields
endpoint.device_id, endpoint.machine_name
Google Drive
gdrive.permission, gdrive.shared_internal_email, gdrive.shared_external_email, gdrive.drive, gdrive.file_owner, gdrive.label_name
Salesforce
salesforce.report.scope, salesforce.report.event_source, salesforce.report.source_ip, salesforce.report.session_level, salesforce.report.operation, salesforce.report.description
salesforce.file.source_ip, salesforce.file.session_level
Security posture events support the same query fields as exfiltration events.
AND: Combine multiple conditions (both must match)
OR: Alternative conditions (either can match)
field:value syntax for exact matches
Example:
Find violations by user and integration:
Search across multiple users:
Filter by channel and state:
Time-based queries:
The MCP server returns structured errors in tool responses:
HTTP-level errors from the API gateway:
Tools that return lists support cursor-based pagination. When more results are available, the response includes a nextPageToken field. Pass this value as pageToken in your next request to fetch the next page.
Simply ask: "Show me the next page of results"
The AI client handles this automatically when you ask for more results.
MCP requests share the same rate limits and quotas as the Nightfall REST API. If you receive a 429 response, wait for the duration indicated in the Retry-After header before retrying.
© 2025 Nightfall AI, Inc. All rights reserved.
For questions or support: support@nightfall.ai
Available Tools
16 integrated security operations tools
get_violation_findings
View sensitive data findings within a violation
get_violation_activity
Review activity timeline and remediation history
take_action_on_violations
Execute remediation actions (resolve, block, delete, etc.)
get_exfiltration_event_activity
View event timeline and status changes
get_posture_event_activity
View event activity history
Enable audit logging in your AI client to track MCP queries for compliance
Clarify formatting preferences: "Show as a table" or "Give me a bullet list"
user_email, user_name: Filter by specific users
last_actioned_by: NIGHTFALL, ADMIN, END_USER
confidence: Detection confidence level
policy_id, detection_rule_id, detector_id: Policy and rule identifiers
teams.chat_participantSERVICE_ERROR
Backend service failure—retry after a moment
INTERNAL_ERROR
Unexpected system error
Endpoint
https://api.nightfall.ai/mcp
Protocol
MCP Streamable HTTP (JSON-RPC 2.0)
Authentication
search_violations
Search violations using structured queries (field:value syntax)
list_violations
Browse recent violations with date range filters
get_violation
search_exfiltration_events
Search exfiltration events with advanced filters
list_exfiltration_events
Browse recent exfiltration events
get_exfiltration_event
search_posture_events
Search for security posture issues
list_posture_events
Browse recent posture events
get_posture_event
get_actor_activity
Get complete user activity history
get_asset_activity
Track file/document activity history
UNAUTHORIZED
Missing or invalid API key
INVALID_INPUT
Malformed parameters or invalid values
NOT_FOUND
401 Unauthorized
Invalid or missing API key
429 Too Many Requests
Rate limit or quota exceeded—check Retry-After header
Security Note: Your API key provides full access to your Nightfall data. Never commit it to version control or share it publicly.
Bearer token (Nightfall API key)
Get full details for a specific violation
Get complete event details and affected assets
Get detailed event information
The requested violation or event does not exist
{
"mcpServers": {
"nightfall": {
"command": "npx",
"args": [
"-y",
"mcp-remote@latest",
"https://api.nightfall.ai/mcp",
"--header",
"Authorization: Bearer YOUR_NIGHTFALL_API_KEY"
]
}
}
}{
"mcpServers": {
"nightfall": {
"url": "https://api.nightfall.ai/mcp",
"headers": {
"Authorization": "Bearer YOUR_NIGHTFALL_API_KEY"
}
}
}
}{
"mcpServers": {
"nightfall": {
"serverUrl": "https://api.nightfall.ai/mcp",
"headers": {
"Authorization": "Bearer YOUR_NIGHTFALL_API_KEY"
}
}
}
}POST https://api.nightfall.ai/mcp
Authorization: Bearer YOUR_NIGHTFALL_API_KEY
Content-Type: application/jsonintegration_name:github AND risk_label:HIGH AND state:ACTIVEuser_email:jane@example.com AND integration_name:slackuser_email:jane@example.com OR user_email:john@example.comslack.channel_name:general AND state:PENDINGcreatedAfter=<unix_timestamp> AND risk_label:HIGHReturns a list of repositories Nightfall has access to.
The maximum number of records to be returned in the response
100Cursor for getting the next page of results
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
The GitHub repository ID
The name of the repository
Whether the repo is private
The URL of the repository
Unix timestamp, the last scan time of any file/commit in the repository. Omitted if not scanned yet.
Whether the repository is covered by a policy
GitHub username in case of a personal account and organization name in case of an organization
Next page cursor, omitted if end of results reached
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /apps/v1/github/repositories HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"repositories": [
{
"repositoryID": 1,
"repositoryName": "text",
"isRepoPrivate": true,
"repoLink": "text",
"scannedAt": 1,
"isMonitored": true,
"githubUsername": "text"
}
],
"nextPageToken": "text"
}Returns a list of endpoint devices where the Nightfall agent is installed across the organization.
The maximum number of agents to be returned in the response
500Cursor for getting the next page of results
Prefix search across device name, device ID, and user email
Filter agents by version status
Filter agents by stealth mode status
Filter agents by profile status
Comma-delimited list of BROWSER:VALUE pairs to filter by browser extension status. VALUE may be either:
true/false) — true matches any installed/connected state, false matches not-installed; orEXTENSION_CONNECTED|EXTENSION_DISCONNECTED)
to match agents whose extension is in any of the listed states. States may be passed in short
form (EXTENSION_CONNECTED) or full form (BROWSER_EXTENSION_INSTALLATION_STATUS_EXTENSION_CONNECTED).
Valid filter states: BROWSER_NOT_INSTALLED, BROWSER_INSTALLED, EXTENSION_INSTALLED, INSTALLATION_PENDING, EXTENSION_CONNECTED, EXTENSION_DISCONNECTED. Any other value (UNKNOWN, ERROR, or the unprefixed CONNECTED/DISCONNECTED forms) is silently dropped. Note: the response status field still echoes the bare proto enum names (e.g. BROWSER_EXTENSION_INSTALLATION_STATUS_CONNECTED) — only filter input uses the EXTENSION_ aliases. Supported browsers: BROWSER_CHROME, BROWSER_EDGE, BROWSER_FIREFOX, BROWSER_SAFARI, BROWSER_ARC, BROWSER_ATLAS, BROWSER_BRAVE, BROWSER_CHROME_BETA, BROWSER_COMET, BROWSER_VIVALDI.BROWSER_CHROME:EXTENSION_CONNECTED|EXTENSION_DISCONNECTED,BROWSER_EDGE:trueSuccessful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
Operating system of the endpoint device
Name of the endpoint device
Unique identifier for the endpoint device
MAC addresses of the endpoint device's network interfaces
Current connection status of the agent
Timestamp of the agent's last connection. Omitted if never connected.
Version of the installed agent
Version of the operating system
Email of the user associated with the agent
Stealth mode status of the agent
Configuration profile installation status
The browser name
Extension installation status for this browser
Whether the extension is connected for any profile
Timestamp of the most recent extension-connection state change (omitted when never reported)
Total number of agents matching the filter criteria
Next page cursor, omitted if end of results reached
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /apps/v1/endpoint/devices HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"agents": [
{
"os": "MAC_OS",
"deviceName": "text",
"deviceId": "text",
"macAddresses": [
"text"
],
"connectionStatus": "ONLINE",
"lastConnection": "2026-01-01T00:00:00.000Z",
"agentVersion": "text",
"osVersion": "text",
"userEmail": "text",
"stealthMode": "STEALTH_MODE_STATUS_UNKNOWN",
"profileStatus": "PROFILE_STATUS_UNKNOWN",
"missingPermissions": [
"AGENT_PERMISSION_FULL_DISK_ACCESS"
],
"errors": [
"AGENT_ERROR_CODE_USER_AGENT_NOT_CONNECTED"
],
"extensionInstallationStatuses": [
{
"browser": "BROWSER_CHROME",
"status": "BROWSER_EXTENSION_INSTALLATION_STATUS_UNKNOWN",
"extensionConnected": true,
"lastConnectionStatusUpdate": "2026-01-01T00:00:00.000Z"
}
]
}
],
"totalAgents": 1,
"nextPageToken": "text"
}Returns a paginated list of domain collections configured for the company.
The maximum number of collections to be returned in the response
50Cursor for getting the next page of results
Sort order for the collection name
ascPossible values: Successful response
Preview of domains belonging to the collection (truncated)
Total number of domains in the collection
Next page cursor, omitted if end of results reached
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /apps/v1/endpoint/collections HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"collections": [
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"source": "MANUAL",
"domains": [
"text"
],
"totalDomains": 1
}
],
"totalCollections": 1,
"nextPageToken": "text"
}Creates a new manual domain collection. Collection names are case-insensitive unique per company and cannot be the reserved value CORPORATE DOMAINS.
Human-readable name for the collection. Case-insensitive unique per company. The value CORPORATE DOMAINS is reserved.
Collection created
Collection identifier
Collection name
How the collection was created. Only MANUAL collections are user-mutable.
Timestamp of the most recent update
Invalid request body
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
A collection with the same name already exists
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Collection name is reserved
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
POST /apps/v1/endpoint/collections HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 15
{
"name": "text"
}{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"source": "MANUAL",
"updatedAt": "2026-01-01T00:00:00.000Z"
}Renames an existing manual domain collection. System collections cannot be renamed.
UUID of the collection
Human-readable name for the collection. Case-insensitive unique per company. The value CORPORATE DOMAINS is reserved.
Collection updated
Collection identifier
Collection name
How the collection was created. Only MANUAL collections are user-mutable.
Timestamp of the most recent update
Invalid request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Collection not found
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
A collection with the same name already exists
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Collection cannot be changed, or name is reserved
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
PUT /apps/v1/endpoint/collections/{collectionUUID} HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 15
{
"name": "text"
}{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"source": "MANUAL",
"updatedAt": "2026-01-01T00:00:00.000Z"
}Soft-deletes a manual domain collection.
UUID of the collection
Collection deleted
No content
Invalid collection ID
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Collection not found
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Collection cannot be changed
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
DELETE /apps/v1/endpoint/collections/{collectionUUID} HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
No content
Returns every active domain attached to the collection.
UUID of the parent collection
Successful response
The domain name
How the domain was originally added (always MANUAL for entries created via this API; other values may appear for entries added through the UI or CSV upload)
Invalid collection ID
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Collection not found
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /apps/v1/endpoint/collections/{collectionUUID}/domains HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"domains": [
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"source": "MANUAL",
"updatedAt": "2026-01-01T00:00:00.000Z"
}
]
}Bulk-adds domains to a collection. Domains added via the workflow API are always recorded with source MANUAL. When the target collection is the reserved CORPORATE DOMAINS collection, personal-email domains are rejected and returned in failedDomains.
UUID of the parent collection
A valid domain name (e.g. example.com)
Domains processed (some may have been rejected as personal domains, see failedDomains)
The domain name
How the domain was originally added (always MANUAL for entries created via this API; other values may appear for entries added through the UI or CSV upload)
Domain names rejected because they are personal-email providers and were targeted at the reserved corporate-domains collection. Omitted when empty.
Invalid request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Collection not found
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
POST /apps/v1/endpoint/collections/{collectionUUID}/domains HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 29
{
"domains": [
{
"name": "text"
}
]
}{
"domains": [
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"source": "MANUAL",
"updatedAt": "2026-01-01T00:00:00.000Z"
}
],
"failedDomains": [
"text"
]
}Soft-deletes a single domain from a collection.
UUID of the parent collection
UUID of the domain to remove
Domain deleted
No content
Invalid collection or domain ID
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Collection or domain not found
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
DELETE /apps/v1/endpoint/collections/{collectionUUID}/domains/{domainUUID} HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
No content
Returns a paginated list of MCP server collections configured for the company.
50Successful response
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /apps/v1/endpoint/mcp-collections HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"collections": [
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"source": "MANUAL",
"totalItems": 1
}
],
"total": 1,
"nextPageToken": "text"
}Creates a new manual MCP server collection. Collection names are case-insensitive unique per company.
Collection created
Invalid request body
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
A collection with the same name already exists
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
POST /apps/v1/endpoint/mcp-collections HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 15
{
"name": "text"
}{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"source": "MANUAL",
"itemCount": 1,
"updatedAt": "2026-01-01T00:00:00.000Z"
}Renames an existing manual MCP server collection. System collections cannot be renamed.
Collection updated
Invalid request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Collection not found
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
A collection with the same name already exists
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Collection cannot be changed
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
PUT /apps/v1/endpoint/mcp-collections/{collectionUUID} HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 15
{
"name": "text"
}{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "text",
"source": "MANUAL",
"itemCount": 1,
"updatedAt": "2026-01-01T00:00:00.000Z"
}Soft-deletes a manual MCP server collection.
Collection deleted
No content
Invalid collection ID
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Collection not found
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Collection cannot be changed
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
DELETE /apps/v1/endpoint/mcp-collections/{collectionUUID} HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
No content
50Successful response
The MCP server name to include in the collection
Optional list of tool names to restrict to. Omit or send an empty list to include all tools on the server.
Invalid request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Collection not found
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /apps/v1/endpoint/mcp-collections/{collectionUUID}/items HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"items": [
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"serverScope": {
"serverName": "text",
"toolNames": [
"text"
]
},
"updatedAt": "2026-01-01T00:00:00.000Z"
}
],
"total": 1,
"nextPageToken": "text"
}Bulk-adds MCP server scopes to a collection. Each scope identifies an MCP server by serverName and optionally restricts the inventoried tools to a list of toolNames. Omitting toolNames means "all tools on this server".
The MCP server name to include in the collection
Optional list of tool names to restrict to. Omit or send an empty list to include all tools on the server.
Items added
The MCP server name to include in the collection
Optional list of tool names to restrict to. Omit or send an empty list to include all tools on the server.
Invalid request body
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Collection not found
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
POST /apps/v1/endpoint/mcp-collections/{collectionUUID}/items HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 54
{
"items": [
{
"serverName": "text",
"toolNames": [
"text"
]
}
]
}{
"items": [
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"serverScope": {
"serverName": "text",
"toolNames": [
"text"
]
},
"updatedAt": "2026-01-01T00:00:00.000Z"
}
]
}Item deleted
No content
Invalid collection or item ID
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Collection or item not found
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
DELETE /apps/v1/endpoint/mcp-collections/{collectionUUID}/items/{itemUUID} HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
No content
Fetch a list of posture events based on some filters
Unix timestamp in seconds, filters records created ≥ the value, defaults to -180 days UTC
Unix timestamp in seconds, filters records created < the value, defaults to end of the current day UTC
Unix timestamp in seconds, filters records updated > the value
The maximum number of records to be returned in the response
50Cursor for getting the next page of results
Sort key and direction, defaults to descending order by creation time
TIME_DESCPossible values: The query containing filter clauses
Query structure and terminology
A query clause consists of a field followed by an operator followed by a value:
| term | value |
|---|---|
| clause | user_email:"amy@rocketrides.io" |
| field | user_email |
| operator | : |
| value | amy@rocketrides.io |
You can combine multiple query clauses in a search by separating them with a space.
Field types, substring matching, and numeric comparators
Every search field supports exact matching with a :. Certain fields such as user_email and user_name support substring matching.
Quotes
You may use quotation marks around string values. Quotation marks are required in case the value contains spaces. For example:
user_mail:john@example.comuser_name:"John Doe"Special Characters
+ - && || ! ( ) { } [ ] ^ " ~ * ? : are special characters need to be escaped using \. For example:
(1+1):2 should be searched for using \(1\+1)\:2Search Syntax
The following table lists the syntax that you can use to construct a query.
| SYNTAX | USAGE | DESCRIPTION | EXAMPLES |
|---|---|---|---|
: | field:value | Exact match operator (case insensitive) | state:"pending" returns records where the currency is exactly "PENDING" in a case-insensitive comparison |
(space) | field1:value1 field2:value2 | The query returns only records that match both clauses | state:active slack.channel_name:general |
OR | field:(value1 OR value2) | The query returns records that match either of the values (case insensitive) | state:(active OR pending) |
Query Fields
| param | description |
|---|---|
| event_id | the unique identifier of the posture event to filter on |
| integration_name | the name of the integration to filter on |
| state | the state of the event to filter on (active, pending, resolved, expired) |
| event_type | the type of posture event to filter on |
| actor_name | the name of the actor who performed the action to filter on |
| actor_email | the email of the actor who performed the action to filter on |
| user_name | the username of the user to filter on (backward compatibility) |
| user_email | the email of the user to filter on (backward compatibility) |
| notes | the comment or notes associated with the event to filter on |
| policy_id | the unique identifier of the policy to filter on |
| policy_name | the name of the policy to filter on |
| resource_id | the identifier of the resource to filter on |
| resource_name | the name of the resource to filter on |
| resource_owner_name | the name of the resource owner to filter on |
| resource_owner_email | the email of the resource owner to filter on |
| resource_content_type | the content type of the resource to filter on |
| endpoint.device_id | the device identifier for endpoint events to filter on |
| endpoint.machine_name | the machine name for endpoint events to filter on |
| gdrive.permission | the permission setting for Google Drive files to filter on |
| gdrive.shared_internal_email | the internal emails with which the file is shared to filter on |
| gdrive.shared_external_email | the external emails with which the file is shared to filter on |
| gdrive.drive | the Google Drive name to filter on |
| gdrive.file_owner | the owner of the Google Drive file to filter on |
| gdrive.label_name | the label name applied to Google Drive files to filter on |
| salesforce.report.scope | the scope of the Salesforce report to filter on |
| salesforce.report.event_source | the event source of the Salesforce report to filter on |
| salesforce.report.source_ip | the source IP address of the Salesforce report to filter on |
| salesforce.report.session_level | the session level of the Salesforce report to filter on |
| salesforce.report.operation | the operation type of the Salesforce report to filter on |
| salesforce.report.description | the description of the Salesforce report to filter on |
| salesforce.file.source_ip | the source IP address for Salesforce file events to filter on |
| salesforce.file.session_level | the session level for Salesforce file events to filter on |
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
Unique identifier for the posture event
Integration type that generated the event (e.g., GDRIVE, ES_WINDOWS, ES_MAC)
Unix timestamp in seconds indicating when the event was created
Current state of the event (e.g., ACTIVE, RESOLVED, EXPIRED, PENDING)
Type of exfiltration event (e.g., PERMISSION_CHANGE, ADD_EXTERNAL_USER)
List of policy UUIDs that triggered the event
Number of assets involved in the posture event
Username of the associated user
Email of the associated user
Link to the user's profile
Device identifier for endpoint events
Machine name for endpoint events
Whether the user is external to the organization
Identifier of the application
Name of the application
Next page cursor, omitted if end of results reached
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /posture/v1/events/search?query=text HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"events": [
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"integration": "text",
"createdAt": 1,
"state": "text",
"eventType": "text",
"policyUUIDs": [
"123e4567-e89b-12d3-a456-426614174000"
],
"assetsCount": 1,
"userInfo": {
"username": "text",
"userEmail": "name@gmail.com",
"userProfileLink": "https://example.com",
"deviceId": "text",
"machineName": "text",
"isExternal": true
},
"appInfo": {
"id": "text",
"name": "text"
}
}
],
"nextPageToken": "text"
}Fetch a list of posture events for a period
Unix timestamp in seconds, filters records created ≥ the value, defaults to -90 days UTC
Unix timestamp in seconds, filters records created < the value, defaults to end of the current day UTC
Unix timestamp in seconds, filters records updated > the value
The maximum number of records to be returned in the response
50Cursor for getting the next page of results
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
Unique identifier for the posture event
Integration type that generated the event (e.g., GDRIVE, ES_WINDOWS, ES_MAC)
Unix timestamp in seconds indicating when the event was created
Current state of the event (e.g., ACTIVE, RESOLVED, EXPIRED, PENDING)
Type of exfiltration event (e.g., PERMISSION_CHANGE, ADD_EXTERNAL_USER)
List of policy UUIDs that triggered the event
Number of assets involved in the posture event
Username of the associated user
Email of the associated user
Link to the user's profile
Device identifier for endpoint events
Machine name for endpoint events
Whether the user is external to the organization
Identifier of the application
Name of the application
Next page cursor, omitted if end of results reached
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /posture/v1/events HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"events": [
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"integration": "text",
"createdAt": 1,
"state": "text",
"eventType": "text",
"policyUUIDs": [
"123e4567-e89b-12d3-a456-426614174000"
],
"assetsCount": 1,
"userInfo": {
"username": "text",
"userEmail": "name@gmail.com",
"userProfileLink": "https://example.com",
"deviceId": "text",
"machineName": "text",
"isExternal": true
},
"appInfo": {
"id": "text",
"name": "text"
}
}
],
"nextPageToken": "text"
}Fetch an posture event details by ID
The UUID of the event to fetch
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
Unique identifier for the asset
Name of the asset
Path to the asset
Size of the asset in bytes
MIME type of the asset
Unique identifier for the actor in Nightfall
Email of the actor
Comment or notes associated with the event
Groups the user belongs to
Whether the user is an admin
Whether the user is suspended
Timestamp when the user was created
Salesforce user metadata (currently empty as per spec)
Comment or notes associated with the asset
array to strings to DDR violations ids associated with the resource
ID of the file
Name of the file
Size of the file
Link to the file
Permission setting for the file
External users with whom the file is shared
Internal users with whom the file is shared
Whether viewers can download the file
Owner of the file
Whether the file is in trash
Timestamp when the file was created
Timestamp when the file was last updated
Drive where the file is located
Labels associated with the file
Type of file permission
Type of Salesforce resource
Action performed on the file
Source IP address
Level of the session
Description of the report
Entity fields displayed in the report
Name of the dashboard
Scope of the report
Operation performed
Number of records
Entities queried in the report
Grouped column headers
Number of columns
Number of rows processed
Source IP address
Source of the event
Level of the session
Query executed
Identifier of the event
Source IP address
Key of the session
Level of the session
Unique identifier for the actor in Nightfall
Email of the actor
Comment or notes associated with the event
Groups the user belongs to
Whether the user is an admin
Whether the user is suspended
Timestamp when the user was created
Salesforce user metadata (currently empty as per spec)
Type of the event
Timestamp of the event
ID of the originating app
Name of the originating app
Whether this is a client sync event
Source IP address
Level of the session
Key of the session
Salesforce user ID
array to string with asset IDs associated with the event
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Event does not exist
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /posture/v1/events/{eventId} HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"assets": {
"id": "text",
"name": "text",
"path": "text",
"sizeBytes": 1,
"mimetype": "text",
"owner": {
"id": "text",
"email": "name@gmail.com",
"comment": "text",
"metadata": {
"gdrive": {
"userBelongsToGroups": [
"text"
],
"isAdmin": true,
"isSuspended": true,
"createdAt": 1
},
"salesforce": {}
}
},
"comment": "text",
"ddrViolationIDs": [],
"metadata": {
"gdrive": {
"fileID": "text",
"fileName": "text",
"fileSize": "text",
"fileLink": "text",
"permissionSetting": "text",
"sharingExternalUsers": [
"text"
],
"sharingInternalUsers": [
"text"
],
"canViewersDownload": true,
"fileOwner": "text",
"isInTrash": true,
"createdAt": 1,
"updatedAt": 1,
"drive": "text",
"labels": [
"text"
],
"filePermissionType": "text"
},
"salesforce": {
"resourceType": "text",
"fileResourceMetadata": {
"fileAction": "text",
"sourceIP": "text",
"sessionLevel": "text"
},
"reportResourceMetadata": {
"description": "text",
"displayEntityFields": [
"text"
],
"dashboardName": "text",
"scope": "text",
"operation": "text",
"recordCount": 1,
"queriedEntities": [
"text"
],
"groupedColumnHeaders": [
"text"
],
"columnCount": 1,
"processedRowCount": 1,
"sourceIP": "text",
"eventSource": "text",
"sessionLevel": "text"
},
"bulkApiResourceMetadata": {
"query": "text",
"eventIdentifier": "text",
"sourceIP": "text",
"sessionKey": "text",
"sessionLevel": "text"
}
}
}
},
"actor": {
"id": "text",
"email": "name@gmail.com",
"comment": "text",
"metadata": {
"gdrive": {
"userBelongsToGroups": [
"text"
],
"isAdmin": true,
"isSuspended": true,
"createdAt": 1
},
"salesforce": {}
}
},
"events": {
"type": "PERMISSION_CHANGE",
"timestamp": 1,
"metadata": {
"gdrive": {
"originatingAppId": "text",
"originatingAppName": "text",
"isClientSyncEvent": true
},
"salesforce": {
"sourceIP": "text",
"sessionLevel": "text",
"sessionKey": "text",
"sfUserId": "text"
}
},
"assetIDs": []
}
}Fetch the activity feed for a specific posture event
The UUID of the posture event
Number of activity items to fetch in one page
50Unix timestamp in seconds, filters activity created > the value
Unix timestamp in seconds, filters activity created < the value
Whether to sort results in descending order (default false)
falseCursor for getting the next page of results
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
Unique identifier for the activity log entry
Human-readable message describing the activity
Unix timestamp in seconds when the activity occurred
Next page cursor, omitted if end of results reached
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Event does not exist
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /posture/v1/events/{eventId}/activity HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"activities": [
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"message": "text",
"timestamp": 1,
"type": "CREATION",
"data": {
"action": "ACKNOWLEDGE",
"userUUID": "123e4567-e89b-12d3-a456-426614174000",
"userName": "text",
"userEmail": "text",
"receiverEmail": "text",
"actionLogData": {
"applyLabelsActionLogData": {
"activityType": "LABELS_SUCCESSFULLY_APPLIED",
"labels": [
"text"
],
"labelUpdatesOnResource": {
"ANY_ADDITIONAL_PROPERTY": "text"
},
"failureReason": "text"
},
"setExpirationActionLogData": {
"expirationTime": 1
},
"revokeAccessActionLogData": {
"revokedEmails": [
"text"
],
"unRevokedEmails": [
"text"
]
},
"notifyEmailActionLogData": {
"receiverEmail": "text"
},
"genericActionLogData": {
"additionalContext": "text"
},
"blockActionActionLogData": {
"isBlocked": true,
"blockReason": "text",
"skippedReason": "text"
}
}
}
}
],
"nextPageToken": "text"
}Fetch the activity history for a specific asset
The ID of the asset to fetch activities for
Unix timestamp in seconds, filters activities created ≥ the value
Unix timestamp in seconds, filters activities created < the value
Cursor for getting the next page of results
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
Type of the activity
Email of the user who performed the activity
Unix timestamp in seconds indicating when the activity occurred
Names of asset involved in the activity
Source of the download
Name of the downloaded file
Domain where the upload occurred
Name of the uploaded file
Cloud application used for synchronization
Name of the synchronized file
Domain related to the clipboard activity
Thick app identifier (e.g. THICK_APP_SLACK, THICK_APP_OUTLOOK)
Name of the generic application
Type of app involved in the clipboard event (e.g. CAT_BROWSER, CAT_THICK_APP, CAT_GENERIC_APP)
Next page cursor, omitted if end of results reached
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /posture/v1/asset/activity?assetID=text&rangeStart=1&rangeEnd=1 HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"activities": [
{
"type": "DOWNLOAD",
"userEmail": "name@gmail.com",
"eventTime": 1,
"assetNames": [
"text"
],
"metadata": {
"downloadEventMetadata": {
"source": "text",
"fileName": "text"
},
"browserUploadMetadata": {
"domain": "text",
"fileName": "text"
},
"cloudSyncMetadata": {
"cloudApp": "text",
"fileName": "text"
},
"clipboardMetadata": {
"browserMetadata": {
"domain": "text"
},
"thickAppMetadata": {
"thickApp": "text"
},
"genericAppMetadata": {
"appName": "text"
},
"appType": "text"
}
}
}
],
"nextPageToken": "text"
}Fetch the activity history for a specific actor
The Nightfall ID of the actor to fetch activities for
Unix timestamp in seconds, filters activities created ≥ the value
Unix timestamp in seconds, filters activities created < the value
Cursor for getting the next page of results
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
Type of the activity
Email of the user who performed the activity
Unix timestamp in seconds indicating when the activity occurred
Names of asset involved in the activity
Source of the download
Name of the downloaded file
Domain where the upload occurred
Name of the uploaded file
Cloud application used for synchronization
Name of the synchronized file
Domain related to the clipboard activity
Thick app identifier (e.g. THICK_APP_SLACK, THICK_APP_OUTLOOK)
Name of the generic application
Type of app involved in the clipboard event (e.g. CAT_BROWSER, CAT_THICK_APP, CAT_GENERIC_APP)
Next page cursor, omitted if end of results reached
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /posture/v1/actor/activity?actorID=text&rangeStart=1&rangeEnd=1 HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"activities": [
{
"type": "DOWNLOAD",
"userEmail": "name@gmail.com",
"eventTime": 1,
"assetNames": [
"text"
],
"metadata": {
"downloadEventMetadata": {
"source": "text",
"fileName": "text"
},
"browserUploadMetadata": {
"domain": "text",
"fileName": "text"
},
"cloudSyncMetadata": {
"cloudApp": "text",
"fileName": "text"
},
"clipboardMetadata": {
"browserMetadata": {
"domain": "text"
},
"thickAppMetadata": {
"thickApp": "text"
},
"genericAppMetadata": {
"appName": "text"
},
"appType": "text"
}
}
}
],
"nextPageToken": "text"
}The request body of the /v3/scan endpoint
A list of UUIDs referring to policies to use to scan the request payload. Policies can be built in the Nightfall Dashboard. Maximum 1.
A list of UUIDs referring to detection rules to use to scan the request payload. Detection rules can be built in the Nightfall dashboard. Maximum 20.
An optional name for the detection rule.
Supported values ALL or ANY. Applies a logical "AND" or "OR" (respectively) to the list of detectors to decide when a finding should be surfaced.
The minimum number of findings required in order for this detector to be reported.
The confidence level of a finding.
The UUID of a pre-existing detector to use. If this value is provided, all below fields are ignored.
The display name for this detector's findings in the response.
The type of detector.
The name for a Nightfall detector.
The regex pattern to match on.
The case sensitivity for the regex pattern.
A list of words for wordList.
The case sensitivity for words in the wordList. If false, ignore the case of findings.
The regex pattern to match on.
The case sensitivity for the regex pattern.
The number of leading characters to include as context before the finding itself.
The number of trailing characters to include as context after the finding itself.
The confidence level of a finding.
The type of match for a pattern.
The type of exclusion rule.
The regex pattern to match on.
The case sensitivity for the regex pattern.
A list of words for wordList.
The case sensitivity for words in the wordList. If false, ignore the case of findings.
The UTF-8 character used to mask a finding. If not provided, we will mask with an asterisk "*". Other examples include "#", "X", "🙅🏽", "🙈", etc.
A list of characters that will not be masked. For example, you could set this field to ["-","@"] to preserve formatting context that is typically present in credit cards or emails (e.g. --- versus *********, or ***************** versus @).
The number of characters that will be left unmasked. When no masking direction is sent, the leading characters are left unmasked: setting this value to 4 redacts a credit card number as 4242************. To leave the trailing 4 digits visible instead (***************4242), also send maskRightToLeft: true.
Controls which end of the finding is left unmasked. Set to true to leave the trailing numCharsToLeaveUnmasked characters unmasked (4242). Set to false, or omit both direction fields, to leave the leading characters unmasked (4242). At most one of maskRightToLeft and maskLeftToRight may be sent in a request; sending both returns an error.
Deprecated: use maskRightToLeft instead. The opposite of maskRightToLeft: set to true to leave the leading numCharsToLeaveUnmasked characters unmasked (4242***************), or false to leave the trailing characters unmasked (***************4242). At most one of maskRightToLeft and maskLeftToRight may be sent in a request; sending both returns an error.
A config that substitutes a sensitive finding with the name of the NIGHTFALL_DETECTOR that triggered it. This config is only valid for detector's with detectorType NIGHTFALL_DETECTOR. e.g. '4242-4242-4242-4242' can be configured to be redacted to '[CREDIT_CARD_NUMBER]'.
The value that will replace a sensitive finding. e.g. '<oh no!🙈>'
The PEM formatted public key block that will be used to encrypt findings. Currently, only RSA encryption is supported.
Here's an example PEM formatted public key block:
-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAydYMwOYUGyBXDgHkzv19 YR/dYQES4kYTMUps39qv/amNDywz4nsBDvCUqUvcN3nEpplHlYGH5ShSeA4G/Fcm RqynSLVyFPZat/8E7n+EeHsgihFrr8oDWo5UBjCwRinTrC0m11q/5SeNzwVCWkf9 x40u94QBz13dQoa9yPwaZBX5uBzyH86R7yeZHpad2cLq0ltpmJ3j5UfsFilkOb3J B60TNpNDdfabprot/y30CEnDDOgAXGtV1m0AhQpQjKRnkUs39DntqSbS+i0Ugbyq zEGNUkeR1WsotXekW4KnbWA7k6S8SfkO27vnTSY5b9g/KKaOdysn5YaWJPfTVT/n ywIDAQAB -----END PUBLIC KEY-----
Determines if the response object will contain the un-redacted sensitive finding that was triggered by the scan. Defaults to false.
The scope to run the detector over. Setting any detector to File will cause it to run against the file name.
The number of bytes to include as before / after context when a finding is returned. Maximum 40.
The UTF-8 character used to mask a finding. If not provided, we will mask with an asterisk "*". Other examples include "#", "X", "🙅🏽", "🙈", etc.
A list of characters that will not be masked. For example, you could set this field to ["-","@"] to preserve formatting context that is typically present in credit cards or emails (e.g. --- versus *********, or ***************** versus @).
The number of characters that will be left unmasked. When no masking direction is sent, the leading characters are left unmasked: setting this value to 4 redacts a credit card number as 4242************. To leave the trailing 4 digits visible instead (***************4242), also send maskRightToLeft: true.
Controls which end of the finding is left unmasked. Set to true to leave the trailing numCharsToLeaveUnmasked characters unmasked (4242). Set to false, or omit both direction fields, to leave the leading characters unmasked (4242). At most one of maskRightToLeft and maskLeftToRight may be sent in a request; sending both returns an error.
Deprecated: use maskRightToLeft instead. The opposite of maskRightToLeft: set to true to leave the leading numCharsToLeaveUnmasked characters unmasked (4242***************), or false to leave the trailing characters unmasked (***************4242). At most one of maskRightToLeft and maskLeftToRight may be sent in a request; sending both returns an error.
A config that substitutes a sensitive finding with the name of the NIGHTFALL_DETECTOR that triggered it. This config is only valid for detector's with detectorType NIGHTFALL_DETECTOR. e.g. '4242-4242-4242-4242' can be configured to be redacted to '[CREDIT_CARD_NUMBER]'.
The value that will replace a sensitive finding. e.g. '<oh no!🙈>'
The PEM formatted public key block that will be used to encrypt findings. Currently, only RSA encryption is supported.
Here's an example PEM formatted public key block:
-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAydYMwOYUGyBXDgHkzv19 YR/dYQES4kYTMUps39qv/amNDywz4nsBDvCUqUvcN3nEpplHlYGH5ShSeA4G/Fcm RqynSLVyFPZat/8E7n+EeHsgihFrr8oDWo5UBjCwRinTrC0m11q/5SeNzwVCWkf9 x40u94QBz13dQoa9yPwaZBX5uBzyH86R7yeZHpad2cLq0ltpmJ3j5UfsFilkOb3J B60TNpNDdfabprot/y30CEnDDOgAXGtV1m0AhQpQjKRnkUs39DntqSbS+i0Ugbyq zEGNUkeR1WsotXekW4KnbWA7k6S8SfkO27vnTSY5b9g/KKaOdysn5YaWJPfTVT/n ywIDAQAB -----END PUBLIC KEY-----
Determines if the response object will contain the un-redacted sensitive finding that was triggered by the scan. Defaults to false.
The name of the Slack conversation to which alerts should be sent. Currently, Nightfall supports sending alerts to public channels, formatted like "#general".
The email address to which alerts should be sent.
The URL to which alerts should be sent. This URL must (1) use the HTTPS scheme, (2) be able to accept requests made with the POST verb, and (3) respond with a 200 status code upon receipt of the event.
The URL to which alerts should be sent. This URL must (1) use the HTTPS scheme, (2) be able to accept requests made with the POST verb, and (3) respond with a 200 status code upon receipt of the event.
The text sample(s) you wish to scan. This data is passed as a string list, so you may choose to segment your text into multiple items for better granularity. The aggregate size of your text (summed across all items in the list) must not exceed 500 KB for any individual request, and the number of items in that list may not exceed 50,000.
Success
the content type of the response
The string that triggered a match during the scan.
The redacted version of finding. This key is omitted if no redactionConfig was configured the detector that triggered the match.
The sequence of bytes that occurred directly prior to the matched finding. The number of bytes is usually equal to the requested number from the request config, but it could be smaller if the finding occurs near the beginning of the payload. This key is omitted if no context was requested.
The sequence of bytes that occurred directly after the matched finding. The number of bytes is usually equal to the requested number from the request config, but it could be smaller if the finding occurs near the end of the payload. This key is omitted if no context was requested.
The display name of the detector that matched the finding.
The UUID of the detector that matched the finding. This UUID can be looked up in the Nightfall dashboard.
The display name of the subdetector that matched the finding.
The UUID of the subdetector that matched the finding. This UUID can be looked up in the Nightfall dashboard.
The confidence level of a finding.
The index of the fragment's starting byte.
The index of the fragment's ending byte.
The index of the fragment's starting codepoint character.
The index of the fragment's ending codepoint character.
The index of the fragment's starting byte.
The index of the fragment's ending byte.
The index of the fragment's starting codepoint character.
The index of the fragment's ending codepoint character.
A list containing the the redacted version of each string in the input payload. If no redactions were applied, the corresponding string will be empty.
Invalid request payload
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Unprocessable request payload
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Monthly Quota Exceeded
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
POST /v3/scan HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 1595
{
"policyUUIDs": [
"text"
],
"policy": {
"detectionRuleUUIDs": [
"text"
],
"detectionRules": [
{
"name": "text",
"logicalOp": "ANY",
"detectors": [
{
"minNumFindings": 1,
"minConfidence": "VERY_UNLIKELY",
"detectorUUID": "text",
"displayName": "text",
"detectorType": "NIGHTFALL_DETECTOR",
"nightfallDetector": "AMERICAN_BANKERS_CUSIP_ID",
"regex": {
"pattern": "text",
"isCaseSensitive": true
},
"wordList": {
"values": [
"text"
],
"isCaseSensitive": true
},
"contextRules": [
{
"regex": {
"pattern": "text",
"isCaseSensitive": true
},
"proximity": {
"windowBefore": 1,
"windowAfter": 1
},
"confidenceAdjustment": {
"fixedConfidence": "VERY_UNLIKELY"
}
}
],
"exclusionRules": [
{
"matchType": "PARTIAL",
"exclusionType": "REGEX",
"regex": {
"pattern": "text",
"isCaseSensitive": true
},
"wordList": {
"values": [
"text"
],
"isCaseSensitive": true
}
}
],
"redactionConfig": {
"maskConfig": {
"maskingChar": "text",
"charsToIgnore": [
"text"
],
"numCharsToLeaveUnmasked": 1,
"maskRightToLeft": true
},
"infoTypeSubstitutionConfig": {},
"substitutionConfig": {
"substitutionPhrase": "text"
},
"cryptoConfig": {
"publicKey": "text"
},
"removeFinding": true
},
"scope": "Content"
}
]
}
],
"contextBytes": 1,
"defaultRedactionConfig": {
"maskConfig": {
"maskingChar": "text",
"charsToIgnore": [
"text"
],
"numCharsToLeaveUnmasked": 1,
"maskRightToLeft": true
},
"infoTypeSubstitutionConfig": {},
"substitutionConfig": {
"substitutionPhrase": "text"
},
"cryptoConfig": {
"publicKey": "text"
},
"removeFinding": true
},
"alertConfig": {
"slack": {
"target": "text"
},
"email": {
"address": "text"
},
"url": {
"address": "text"
},
"siem": {
"address": "text",
"sensitiveHeaders": {
"ANY_ADDITIONAL_PROPERTY": "text"
},
"plainTextHeaders": {
"ANY_ADDITIONAL_PROPERTY": "text"
}
}
}
},
"payload": [
"text"
]
}{
"findings": [
[
{
"finding": "text",
"redactedFinding": "text",
"beforeContext": "text",
"afterContext": "text",
"detector": {
"name": "text",
"uuid": "123e4567-e89b-12d3-a456-426614174000",
"subdetector": {
"name": "text",
"uuid": "123e4567-e89b-12d3-a456-426614174000"
}
},
"confidence": "VERY_UNLIKELY",
"location": {
"byteRange": {
"start": 1,
"end": 1
},
"codepointRange": {
"start": 1,
"end": 1
}
},
"redactedLocation": {
"byteRange": {
"start": 1,
"end": 1
},
"codepointRange": {
"start": 1,
"end": 1
}
}
}
]
],
"redactedPayload": [
"text"
]
}the number of bytes representing the size of the file to-be-uploaded.
Success
the content type of the response
a UUID to uniquely identify a particular file upload
the size of the file in bytes
the number of bytes to upload in each chunk upload request
an RFC2045 media type that describes the underlying content type
Invalid request payload
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Monthly Quota Exceeded
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
POST /v3/upload HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 19
{
"fileSizeBytes": 1
}{
"id": "123e4567-e89b-12d3-a456-426614174000",
"fileSizeBytes": 1,
"chunkSize": 1,
"mimeType": "text"
}a file ID returned from a previous file creation request
The numeric offset at which the bytes contained in the body should be written. This offset must be a multiple of the chunk size returned when the file upload was created.
The payload bytes to upload; the size of the request body must exactly match the chunkSize that was returned when the file upload was created.
Success
the content type of the response
Invalid request payload
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Invalid File ID
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Monthly Quota Exceeded
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
PATCH /v3/upload/{fileId} HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
X-Upload-Offset: 1
Content-Type: application/octet-stream
Accept: */*
No content
Validates that all bytes of the file have been uploaded, and that the content type is supported by Nightfall.
a file ID returned from a previous file creation request
Success
the content type of the response
a UUID to uniquely identify a particular file upload
the size of the file in bytes
the number of bytes to upload in each chunk upload request
an RFC2045 media type that describes the underlying content type
Invalid request payload
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Invalid File ID
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
File Upload in Incorrect State
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Monthly Quota Exceeded
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
POST /v3/upload/{fileId}/finish HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"fileSizeBytes": 1,
"chunkSize": 1,
"mimeType": "text"
}a file ID returned from a previous file creation request
the UUID of the Detection Policy to be used with this scan. Exactly one of this field or "policy" should be provided.
the URL that Nightfall shall deliver webhooks to when the scan completes. The URL must use the HTTPS scheme. This field has been deprecated in favor of the more general 'alertConfig'.
A list of pre-existing detection rule UUIDs to scan a file against. These UUIDs can be fetched from the Nightfall Dashboard.
An optional name for the detection rule.
Supported values ALL or ANY. Applies a logical "AND" or "OR" (respectively) to the list of detectors to decide when a finding should be surfaced.
The minimum number of findings required in order for this detector to be reported.
The confidence level of a finding.
The UUID of a pre-existing detector to use. If this value is provided, all below fields are ignored.
The display name for this detector's findings in the response.
The type of detector.
The name for a Nightfall detector.
The regex pattern to match on.
The case sensitivity for the regex pattern.
A list of words for wordList.
The case sensitivity for words in the wordList. If false, ignore the case of findings.
The regex pattern to match on.
The case sensitivity for the regex pattern.
The number of leading characters to include as context before the finding itself.
The number of trailing characters to include as context after the finding itself.
The confidence level of a finding.
The type of match for a pattern.
The type of exclusion rule.
The regex pattern to match on.
The case sensitivity for the regex pattern.
A list of words for wordList.
The case sensitivity for words in the wordList. If false, ignore the case of findings.
The UTF-8 character used to mask a finding. If not provided, we will mask with an asterisk "*". Other examples include "#", "X", "🙅🏽", "🙈", etc.
A list of characters that will not be masked. For example, you could set this field to ["-","@"] to preserve formatting context that is typically present in credit cards or emails (e.g. --- versus *********, or ***************** versus @).
The number of characters that will be left unmasked. When no masking direction is sent, the leading characters are left unmasked: setting this value to 4 redacts a credit card number as 4242************. To leave the trailing 4 digits visible instead (***************4242), also send maskRightToLeft: true.
Controls which end of the finding is left unmasked. Set to true to leave the trailing numCharsToLeaveUnmasked characters unmasked (4242). Set to false, or omit both direction fields, to leave the leading characters unmasked (4242). At most one of maskRightToLeft and maskLeftToRight may be sent in a request; sending both returns an error.
Deprecated: use maskRightToLeft instead. The opposite of maskRightToLeft: set to true to leave the leading numCharsToLeaveUnmasked characters unmasked (4242***************), or false to leave the trailing characters unmasked (***************4242). At most one of maskRightToLeft and maskLeftToRight may be sent in a request; sending both returns an error.
A config that substitutes a sensitive finding with the name of the NIGHTFALL_DETECTOR that triggered it. This config is only valid for detector's with detectorType NIGHTFALL_DETECTOR. e.g. '4242-4242-4242-4242' can be configured to be redacted to '[CREDIT_CARD_NUMBER]'.
The value that will replace a sensitive finding. e.g. '<oh no!🙈>'
The PEM formatted public key block that will be used to encrypt findings. Currently, only RSA encryption is supported.
Here's an example PEM formatted public key block:
-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAydYMwOYUGyBXDgHkzv19 YR/dYQES4kYTMUps39qv/amNDywz4nsBDvCUqUvcN3nEpplHlYGH5ShSeA4G/Fcm RqynSLVyFPZat/8E7n+EeHsgihFrr8oDWo5UBjCwRinTrC0m11q/5SeNzwVCWkf9 x40u94QBz13dQoa9yPwaZBX5uBzyH86R7yeZHpad2cLq0ltpmJ3j5UfsFilkOb3J B60TNpNDdfabprot/y30CEnDDOgAXGtV1m0AhQpQjKRnkUs39DntqSbS+i0Ugbyq zEGNUkeR1WsotXekW4KnbWA7k6S8SfkO27vnTSY5b9g/KKaOdysn5YaWJPfTVT/n ywIDAQAB -----END PUBLIC KEY-----
Determines if the response object will contain the un-redacted sensitive finding that was triggered by the scan. Defaults to false.
The scope to run the detector over. Setting any detector to File will cause it to run against the file name.
The name of the Slack conversation to which alerts should be sent. Currently, Nightfall supports sending alerts to public channels, formatted like "#general".
The email address to which alerts should be sent.
The URL to which alerts should be sent. This URL must (1) use the HTTPS scheme, (2) be able to accept requests made with the POST verb, and (3) respond with a 200 status code upon receipt of the event.
The URL to which alerts should be sent. This URL must (1) use the HTTPS scheme, (2) be able to accept requests made with the POST verb, and (3) respond with a 200 status code upon receipt of the event.
The UTF-8 character used to mask a finding. If not provided, we will mask with an asterisk "*". Other examples include "#", "X", "🙅🏽", "🙈", etc.
A list of characters that will not be masked. For example, you could set this field to ["-","@"] to preserve formatting context that is typically present in credit cards or emails (e.g. --- versus *********, or ***************** versus @).
The number of characters that will be left unmasked. When no masking direction is sent, the leading characters are left unmasked: setting this value to 4 redacts a credit card number as 4242************. To leave the trailing 4 digits visible instead (***************4242), also send maskRightToLeft: true.
Controls which end of the finding is left unmasked. Set to true to leave the trailing numCharsToLeaveUnmasked characters unmasked (4242). Set to false, or omit both direction fields, to leave the leading characters unmasked (4242). At most one of maskRightToLeft and maskLeftToRight may be sent in a request; sending both returns an error.
Deprecated: use maskRightToLeft instead. The opposite of maskRightToLeft: set to true to leave the leading numCharsToLeaveUnmasked characters unmasked (4242***************), or false to leave the trailing characters unmasked (***************4242). At most one of maskRightToLeft and maskLeftToRight may be sent in a request; sending both returns an error.
A config that substitutes a sensitive finding with the name of the NIGHTFALL_DETECTOR that triggered it. This config is only valid for detector's with detectorType NIGHTFALL_DETECTOR. e.g. '4242-4242-4242-4242' can be configured to be redacted to '[CREDIT_CARD_NUMBER]'.
The value that will replace a sensitive finding. e.g. '<oh no!🙈>'
The PEM formatted public key block that will be used to encrypt findings. Currently, only RSA encryption is supported.
Here's an example PEM formatted public key block:
-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAydYMwOYUGyBXDgHkzv19 YR/dYQES4kYTMUps39qv/amNDywz4nsBDvCUqUvcN3nEpplHlYGH5ShSeA4G/Fcm RqynSLVyFPZat/8E7n+EeHsgihFrr8oDWo5UBjCwRinTrC0m11q/5SeNzwVCWkf9 x40u94QBz13dQoa9yPwaZBX5uBzyH86R7yeZHpad2cLq0ltpmJ3j5UfsFilkOb3J B60TNpNDdfabprot/y30CEnDDOgAXGtV1m0AhQpQjKRnkUs39DntqSbS+i0Ugbyq zEGNUkeR1WsotXekW4KnbWA7k6S8SfkO27vnTSY5b9g/KKaOdysn5YaWJPfTVT/n ywIDAQAB -----END PUBLIC KEY-----
Determines if the response object will contain the un-redacted sensitive finding that was triggered by the scan. Defaults to false.
Determines if a redacted version of the file will be returned, if available for the mime type. Current supported mime types are CSV and TSV. Defaults to false.
A string containing arbitrary metadata. Callers may opt to use this to help identify their input file upon receiving a webhook response. Maximum length 10 KB.
Success
the content type of the response
a UUID to uniquely identify a particular file upload
message indicating that file scanning has been initiated
Invalid request payload
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Invalid File ID
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Incorrect File State
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Unprocessable request payload
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Monthly Quota Exceeded
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
POST /v3/upload/{fileId}/scan HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 1672
{
"policyUUID": "123e4567-e89b-12d3-a456-426614174000",
"policy": {
"detectionRuleUUIDs": [
"123e4567-e89b-12d3-a456-426614174000"
],
"detectionRules": [
{
"name": "text",
"logicalOp": "ANY",
"detectors": [
{
"minNumFindings": 1,
"minConfidence": "VERY_UNLIKELY",
"detectorUUID": "text",
"displayName": "text",
"detectorType": "NIGHTFALL_DETECTOR",
"nightfallDetector": "AMERICAN_BANKERS_CUSIP_ID",
"regex": {
"pattern": "text",
"isCaseSensitive": true
},
"wordList": {
"values": [
"text"
],
"isCaseSensitive": true
},
"contextRules": [
{
"regex": {
"pattern": "text",
"isCaseSensitive": true
},
"proximity": {
"windowBefore": 1,
"windowAfter": 1
},
"confidenceAdjustment": {
"fixedConfidence": "VERY_UNLIKELY"
}
}
],
"exclusionRules": [
{
"matchType": "PARTIAL",
"exclusionType": "REGEX",
"regex": {
"pattern": "text",
"isCaseSensitive": true
},
"wordList": {
"values": [
"text"
],
"isCaseSensitive": true
}
}
],
"redactionConfig": {
"maskConfig": {
"maskingChar": "text",
"charsToIgnore": [
"text"
],
"numCharsToLeaveUnmasked": 1,
"maskRightToLeft": true
},
"infoTypeSubstitutionConfig": {},
"substitutionConfig": {
"substitutionPhrase": "text"
},
"cryptoConfig": {
"publicKey": "text"
},
"removeFinding": true
},
"scope": "Content"
}
]
}
],
"alertConfig": {
"slack": {
"target": "text"
},
"email": {
"address": "text"
},
"url": {
"address": "text"
},
"siem": {
"address": "text",
"sensitiveHeaders": {
"ANY_ADDITIONAL_PROPERTY": "text"
},
"plainTextHeaders": {
"ANY_ADDITIONAL_PROPERTY": "text"
}
}
},
"defaultRedactionConfig": {
"maskConfig": {
"maskingChar": "text",
"charsToIgnore": [
"text"
],
"numCharsToLeaveUnmasked": 1,
"maskRightToLeft": true
},
"infoTypeSubstitutionConfig": {},
"substitutionConfig": {
"substitutionPhrase": "text"
},
"cryptoConfig": {
"publicKey": "text"
},
"removeFinding": true
},
"enableFileRedaction": true
},
"requestMetadata": "text"
}{
"id": "123e4567-e89b-12d3-a456-426614174000",
"message": "text"
}Maximum number of records to return (default 20, max 100)
Opaque pagination cursor returned as nextPageToken in a prior response
Sort order (default DEVICE_COUNT_DESC)
Case-insensitive match on the server name
Exact match on transport (e.g. stdio, http, sse)
An AI coding client, normalized. Endpoint agents report client names inconsistently — the same client arrives with different casing, spacing and separators depending on which config file or process reported it — so every client field and client filter on this API uses this closed vocabulary instead of the raw name.
UNKNOWN is a response value only, never a filter value: it means the reported name did not match a known client, and the raw name is then returned alongside in the accompanying unrecognizedClient field or unrecognizedClients list.
CLAUDE covers the Claude desktop app as well as the Claude client. VSCODE means Visual Studio Code itself; a Code-based product with its own identity, such as Cursor or Windsurf, reports as itself.
Unix timestamp in seconds; exclude servers not active since this time
Restrict to servers declared by an MDM/enterprise-managed config file (MANAGED) or by a user-writable one (UNMANAGED). Omit to return both.
Include servers whose declaration has disappeared from its config file. Such rows carry removedAt and keep the state they were in when they disappeared. Defaults to false, and total moves with it. A pageToken is only valid for the filter set that produced it: changing this value (or any other filter) mid-pagination silently restarts from the first page with a freshly recomputed total, rather than returning an error. Finish a pagination run before changing filters. Has no effect on tenants where removal reconciliation is not yet enabled.
falseSuccessful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
Opaque server id. Use this value in path parameters; it encodes the (fingerprint, version) key.
The server fingerprint (e.g. "npm:@scope/pkg", "oci:image:tag", "url:domain").
Transport mechanism (stdio, http, sse, etc.)
True when the server is not associated with any known client.
An AI coding client, normalized. Endpoint agents report client names inconsistently — the same client arrives with different casing, spacing and separators depending on which config file or process reported it — so every client field and client filter on this API uses this closed vocabulary instead of the raw name.
UNKNOWN is a response value only, never a filter value: it means the reported name did not match a known client, and the raw name is then returned alongside in the accompanying unrecognizedClient field or unrecognizedClients list.
CLAUDE covers the Claude desktop app as well as the Claude client. VSCODE means Visual Studio Code itself; a Code-based product with its own identity, such as Cursor or Windsurf, reports as itself.
Names observed against this server that are not a known AI client, verbatim. On this inventory they are mostly process names seen spawning a server — xpcproxy, com.docker.backend, iTerm2, node-<hash> — kept here rather than folded into the vocabulary or dropped. Omitted when empty.
Provenance classification. UNKNOWN means the server's identity did not resolve to a registry entry, and is also the value for a row whose classification has not run yet — it is never reported as an empty value. FIRST_PARTY appears only where an administrator has set it.
True when an operator has pinned the provenance, rather than it being derived.
True when an operator has pinned the risk level, rather than it being derived.
True when the server is declared by an MDM/enterprise-managed config file.
Number of distinct clients that have used this server — always equal to clients.length + unrecognizedClients.length, since both are counted after spelling normalization.
Unix timestamp (seconds) of first observation.
Unix timestamp (seconds) of last activity. Omitted when never used.
Unix timestamp (seconds) at which the server's declaration was found to have disappeared from its config file. Omitted while the server is still declared — presence is signalled by the field's absence, not by a zero value. Only ever populated when the request set includeRemoved=true.
Source registry (npm, pypi, oci, etc.)
Total matching servers (present on the first page)
Opaque cursor for the next page; omitted when there are no more results
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /ai-governance/v1/mcp-servers HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"mcpServers": [
{
"id": "text",
"serverId": "text",
"canonicalName": "text",
"version": "text",
"transport": "text",
"risk": 1,
"riskLabel": "text",
"isShadow": true,
"remoteUrl": "text",
"clients": [
"ANTIGRAVITY"
],
"unrecognizedClients": [
"text"
],
"provenance": "FIRST_PARTY",
"provenanceOverridden": true,
"riskOverridden": true,
"isManaged": true,
"deviceCount": 1,
"clientCount": 1,
"totalSpawns": 1,
"totalNetworkCalls": 1,
"totalRequestBytes": 1,
"totalResponseBytes": 1,
"firstSeen": 1,
"lastUsed": 1,
"removedAt": 1,
"registry": {
"name": "text",
"description": "text",
"isOfficial": true,
"isVerified": true,
"popularityScore": 1,
"repositoryUrl": "text",
"websiteUrl": "text",
"license": "text",
"packageName": "text",
"packageRegistry": "text"
}
}
],
"total": 1,
"nextPageToken": "text"
}Opaque MCP server id from a list response
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
Opaque server id. Use this value in path parameters; it encodes the (fingerprint, version) key.
The server fingerprint (e.g. "npm:@scope/pkg", "oci:image:tag", "url:domain").
Transport mechanism (stdio, http, sse, etc.)
True when the server is not associated with any known client.
An AI coding client, normalized. Endpoint agents report client names inconsistently — the same client arrives with different casing, spacing and separators depending on which config file or process reported it — so every client field and client filter on this API uses this closed vocabulary instead of the raw name.
UNKNOWN is a response value only, never a filter value: it means the reported name did not match a known client, and the raw name is then returned alongside in the accompanying unrecognizedClient field or unrecognizedClients list.
CLAUDE covers the Claude desktop app as well as the Claude client. VSCODE means Visual Studio Code itself; a Code-based product with its own identity, such as Cursor or Windsurf, reports as itself.
Names observed against this server that are not a known AI client, verbatim. On this inventory they are mostly process names seen spawning a server — xpcproxy, com.docker.backend, iTerm2, node-<hash> — kept here rather than folded into the vocabulary or dropped. Omitted when empty.
Provenance classification. UNKNOWN means the server's identity did not resolve to a registry entry, and is also the value for a row whose classification has not run yet — it is never reported as an empty value. FIRST_PARTY appears only where an administrator has set it.
True when an operator has pinned the provenance, rather than it being derived.
True when an operator has pinned the risk level, rather than it being derived.
True when the server is declared by an MDM/enterprise-managed config file.
Number of distinct clients that have used this server — always equal to clients.length + unrecognizedClients.length, since both are counted after spelling normalization.
Unix timestamp (seconds) of first observation.
Unix timestamp (seconds) of last activity. Omitted when never used.
Unix timestamp (seconds) at which the server's declaration was found to have disappeared from its config file. Omitted while the server is still declared — presence is signalled by the field's absence, not by a zero value. Only ever populated when the request set includeRemoved=true.
Source registry (npm, pypi, oci, etc.)
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
MCP server does not exist
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /ai-governance/v1/mcp-servers/{serverId} HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"id": "text",
"serverId": "text",
"canonicalName": "text",
"version": "text",
"transport": "text",
"risk": 1,
"riskLabel": "text",
"isShadow": true,
"remoteUrl": "text",
"clients": [
"ANTIGRAVITY"
],
"unrecognizedClients": [
"text"
],
"provenance": "FIRST_PARTY",
"provenanceOverridden": true,
"riskOverridden": true,
"isManaged": true,
"deviceCount": 1,
"clientCount": 1,
"totalSpawns": 1,
"totalNetworkCalls": 1,
"totalRequestBytes": 1,
"totalResponseBytes": 1,
"firstSeen": 1,
"lastUsed": 1,
"removedAt": 1,
"registry": {
"name": "text",
"description": "text",
"isOfficial": true,
"isVerified": true,
"popularityScore": 1,
"repositoryUrl": "text",
"websiteUrl": "text",
"license": "text",
"packageName": "text",
"packageRegistry": "text"
}
}Opaque MCP server id from a list response
Sort order (default LAST_USED_DESC)
Match on device id, machine name, user name, or user email
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
Unix timestamp (seconds) of last activity on this device.
An AI coding client, normalized. Endpoint agents report client names inconsistently — the same client arrives with different casing, spacing and separators depending on which config file or process reported it — so every client field and client filter on this API uses this closed vocabulary instead of the raw name.
UNKNOWN is a response value only, never a filter value: it means the reported name did not match a known client, and the raw name is then returned alongside in the accompanying unrecognizedClient field or unrecognizedClients list.
CLAUDE covers the Claude desktop app as well as the Claude client. VSCODE means Visual Studio Code itself; a Code-based product with its own identity, such as Cursor or Windsurf, reports as itself.
The reported client name, verbatim, when client is UNKNOWN. Omitted otherwise.
Unix timestamp (seconds) of last activity for this client.
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /ai-governance/v1/mcp-servers/{serverId}/devices HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"devices": [
{
"deviceId": "text",
"userEmail": "text",
"userName": "text",
"machineName": "text",
"totalSpawns": 1,
"totalNetworkCalls": 1,
"totalRequestBytes": 1,
"totalResponseBytes": 1,
"lastUsed": 1,
"clientBreakdown": [
{
"client": "ANTIGRAVITY",
"unrecognizedClient": "text",
"configuredName": "text",
"stdioTimesSpawned": 1,
"timesNetworkCalled": 1,
"lastUsedAt": 1,
"isShadow": true
}
]
}
],
"total": 1,
"nextPageToken": "text"
}Sort order (default SERVER_COUNT_DESC)
Match on device machine name
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
Number of AI agent hooks configured on the device. Excludes marketplace-catalog hooks, which are advertised by a plugin catalog but not installed on the machine.
Number of AI agent plugins on the device, including plugins known only from a marketplace catalog entry.
Number of distinct installed (extensionId, version) pairs on the device. Equals the total of GET /ai-governance/v1/ide-extensions?deviceId= with no other filter, so the badge and that drill-down always agree.
Unix timestamp (seconds) of last activity across all servers.
Unix timestamp (seconds) of first observation across all servers.
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /ai-governance/v1/devices HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"devices": [
{
"deviceId": "text",
"serverCount": 1,
"hookCount": 1,
"pluginCount": 1,
"extensionCount": 1,
"totalSpawns": 1,
"totalNetworkCalls": 1,
"lastActive": 1,
"firstSeen": 1,
"machineName": "text",
"os": "text",
"osVersion": "text",
"userEmail": "text",
"agentStatus": "text"
}
],
"total": 1,
"nextPageToken": "text"
}Device id from a device list response
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
Number of AI agent hooks configured on the device. Excludes marketplace-catalog hooks, which are advertised by a plugin catalog but not installed on the machine.
Number of AI agent plugins on the device, including plugins known only from a marketplace catalog entry.
Number of distinct installed (extensionId, version) pairs on the device. Equals the total of GET /ai-governance/v1/ide-extensions?deviceId= with no other filter, so the badge and that drill-down always agree.
Unix timestamp (seconds) of last activity across all servers.
Unix timestamp (seconds) of first observation across all servers.
Opaque server id. Use this value in path parameters; it encodes the (fingerprint, version) key.
The server fingerprint (e.g. "npm:@scope/pkg", "oci:image:tag", "url:domain").
Transport mechanism (stdio, http, sse, etc.)
True when the server is not associated with any known client.
An AI coding client, normalized. Endpoint agents report client names inconsistently — the same client arrives with different casing, spacing and separators depending on which config file or process reported it — so every client field and client filter on this API uses this closed vocabulary instead of the raw name.
UNKNOWN is a response value only, never a filter value: it means the reported name did not match a known client, and the raw name is then returned alongside in the accompanying unrecognizedClient field or unrecognizedClients list.
CLAUDE covers the Claude desktop app as well as the Claude client. VSCODE means Visual Studio Code itself; a Code-based product with its own identity, such as Cursor or Windsurf, reports as itself.
Names observed against this server that are not a known AI client, verbatim. On this inventory they are mostly process names seen spawning a server — xpcproxy, com.docker.backend, iTerm2, node-<hash> — kept here rather than folded into the vocabulary or dropped. Omitted when empty.
Provenance classification. UNKNOWN means the server's identity did not resolve to a registry entry, and is also the value for a row whose classification has not run yet — it is never reported as an empty value. FIRST_PARTY appears only where an administrator has set it.
True when an operator has pinned the provenance, rather than it being derived.
True when an operator has pinned the risk level, rather than it being derived.
True when the server is declared by an MDM/enterprise-managed config file.
Number of distinct clients that have used this server — always equal to clients.length + unrecognizedClients.length, since both are counted after spelling normalization.
Unix timestamp (seconds) of first observation.
Unix timestamp (seconds) of last activity. Omitted when never used.
Unix timestamp (seconds) at which the server's declaration was found to have disappeared from its config file. Omitted while the server is still declared — presence is signalled by the field's absence, not by a zero value. Only ever populated when the request set includeRemoved=true.
Source registry (npm, pypi, oci, etc.)
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Device does not exist
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /ai-governance/v1/devices/{deviceId} HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"device": {
"deviceId": "text",
"serverCount": 1,
"hookCount": 1,
"pluginCount": 1,
"extensionCount": 1,
"totalSpawns": 1,
"totalNetworkCalls": 1,
"lastActive": 1,
"firstSeen": 1,
"machineName": "text",
"os": "text",
"osVersion": "text",
"userEmail": "text",
"agentStatus": "text"
},
"mcpServers": [
{
"id": "text",
"serverId": "text",
"canonicalName": "text",
"version": "text",
"transport": "text",
"risk": 1,
"riskLabel": "text",
"isShadow": true,
"remoteUrl": "text",
"clients": [
"ANTIGRAVITY"
],
"unrecognizedClients": [
"text"
],
"provenance": "FIRST_PARTY",
"provenanceOverridden": true,
"riskOverridden": true,
"isManaged": true,
"deviceCount": 1,
"clientCount": 1,
"totalSpawns": 1,
"totalNetworkCalls": 1,
"totalRequestBytes": 1,
"totalResponseBytes": 1,
"firstSeen": 1,
"lastUsed": 1,
"removedAt": 1,
"registry": {
"name": "text",
"description": "text",
"isOfficial": true,
"isVerified": true,
"popularityScore": 1,
"repositoryUrl": "text",
"websiteUrl": "text",
"license": "text",
"packageName": "text",
"packageRegistry": "text"
}
}
]
}Maximum number of records to return (default 20, max 100)
Opaque pagination cursor returned as nextPageToken in a prior response
Case-insensitive match on the plugin name
An AI coding client, normalized. Endpoint agents report client names inconsistently — the same client arrives with different casing, spacing and separators depending on which config file or process reported it — so every client field and client filter on this API uses this closed vocabulary instead of the raw name.
UNKNOWN is a response value only, never a filter value: it means the reported name did not match a known client, and the raw name is then returned alongside in the accompanying unrecognizedClient field or unrecognizedClients list.
CLAUDE covers the Claude desktop app as well as the Claude client. VSCODE means Visual Studio Code itself; a Code-based product with its own identity, such as Cursor or Windsurf, reports as itself.
Restrict to plugins declared by an MDM/enterprise-managed config file (MANAGED) or by a user-writable one (UNMANAGED). Omit to return both.
Include plugins whose declaration has disappeared from every file that declared them. Such rows carry removedAt and keep the state they were in when they disappeared. Defaults to false, and total moves with it. A pageToken is only valid for the filter set that produced it: changing this value (or any other filter) mid-pagination silently restarts from the first page with a freshly recomputed total, rather than returning an error. Has no effect on tenants where removal reconciliation is not yet enabled.
falseSuccessful response
Opaque plugin id. Use in path parameters; encodes the (client, marketplace, name) key.
An AI coding client, normalized. Endpoint agents report client names inconsistently — the same client arrives with different casing, spacing and separators depending on which config file or process reported it — so every client field and client filter on this API uses this closed vocabulary instead of the raw name.
UNKNOWN is a response value only, never a filter value: it means the reported name did not match a known client, and the raw name is then returned alongside in the accompanying unrecognizedClient field or unrecognizedClients list.
CLAUDE covers the Claude desktop app as well as the Claude client. VSCODE means Visual Studio Code itself; a Code-based product with its own identity, such as Cursor or Windsurf, reports as itself.
The reported client name, verbatim, when client is UNKNOWN. Omitted otherwise.
Marketplace reference the plugin was sourced from. Empty for a plugin declared inline.
Lifecycle state, reported as the highest state any declaring file claims. ENABLED means a settings entry enables it; INSTALLED means it is present on disk but not enabled; AVAILABLE is the bottom of the ladder.
UNKNOWN means the state could not be determined. It is a response value only and is not accepted by the status filter — which is precisely why it exists: a displayed value that the filter cannot reach would make rows disappear from the filter that shows them.
BLOCKED means the plugin matched an enterprise blocklist entry. UNKNOWN is everything else — nothing in this inventory asserts a positive trust decision.
True when declared by an MDM/enterprise-managed config file.
MCP servers the plugin declares.
Hooks the plugin declares.
App declarations the plugin carries.
Unix timestamp (seconds) at which the last file declaring this plugin stopped declaring it. Omitted while it is still declared — presence is signalled by the field's absence, not by a zero value.
Total matching plugins (present on the first page)
Opaque cursor for the next page; omitted when there are no more results
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /ai-governance/v1/plugins HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"plugins": [
{
"id": "text",
"client": "ANTIGRAVITY",
"unrecognizedClient": "text",
"marketplace": "text",
"name": "text",
"version": "text",
"status": "INSTALLED",
"trustState": "BLOCKED",
"provenance": "FIRST_PARTY",
"isManaged": true,
"description": "text",
"author": "text",
"repositoryUrl": "text",
"deviceCount": 1,
"bundledMcpCount": 1,
"bundledHookCount": 1,
"bundledAppCount": 1,
"removedAt": 1
}
],
"total": 1,
"nextPageToken": "text"
}Opaque plugin id from a list response; it encodes the (client, marketplace, name, version) key. Version is part of the identity because the rollup is per version — one plugin name can occupy several rows, each with its own deviceCount — so pass the id from the row you want, unmodified.
Match on device id, machine name, user name, or user email
Successful response
An AI coding client, normalized. Endpoint agents report client names inconsistently — the same client arrives with different casing, spacing and separators depending on which config file or process reported it — so every client field and client filter on this API uses this closed vocabulary instead of the raw name.
UNKNOWN is a response value only, never a filter value: it means the reported name did not match a known client, and the raw name is then returned alongside in the accompanying unrecognizedClient field or unrecognizedClients list.
CLAUDE covers the Claude desktop app as well as the Claude client. VSCODE means Visual Studio Code itself; a Code-based product with its own identity, such as Cursor or Windsurf, reports as itself.
The reported client name, verbatim, when client is UNKNOWN. Omitted otherwise.
See Plugin.status. UNKNOWN is a response value only, never a filter value.
True when an operator has pinned the provenance rather than it being derived.
See Plugin.status. UNKNOWN is a response value only, never a filter value.
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Plugin is not present on any device. Only returned for an unfiltered first page: a request carrying search or pageToken returns 200 with an empty list instead, because neither an empty filtered result nor a page past the end proves the plugin is absent.
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /ai-governance/v1/plugins/{pluginId}/devices HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"plugin": {
"id": "text",
"client": "ANTIGRAVITY",
"unrecognizedClient": "text",
"marketplace": "text",
"name": "text",
"status": "INSTALLED",
"trustState": "BLOCKED",
"provenance": "FIRST_PARTY",
"provenanceOverridden": true,
"description": "text",
"author": "text",
"repositoryUrl": "text"
},
"devices": [
{
"deviceId": "text",
"userEmail": "text",
"userName": "text",
"machineName": "text",
"status": "INSTALLED",
"trustState": "BLOCKED",
"version": "text",
"bundledMcpCount": 1,
"bundledHookCount": 1,
"bundledAppCount": 1
}
],
"total": 1,
"nextPageToken": "text"
}See the same parameter on /plugins.
falseSuccessful response
The same opaque plugin id as the company rollup, so a caller can pivot between the two views.
An AI coding client, normalized. Endpoint agents report client names inconsistently — the same client arrives with different casing, spacing and separators depending on which config file or process reported it — so every client field and client filter on this API uses this closed vocabulary instead of the raw name.
UNKNOWN is a response value only, never a filter value: it means the reported name did not match a known client, and the raw name is then returned alongside in the accompanying unrecognizedClient field or unrecognizedClients list.
CLAUDE covers the Claude desktop app as well as the Claude client. VSCODE means Visual Studio Code itself; a Code-based product with its own identity, such as Cursor or Windsurf, reports as itself.
The reported client name, verbatim, when client is UNKNOWN. Omitted otherwise.
See Plugin.status. UNKNOWN is a response value only, never a filter value.
How the plugin was obtained (e.g. git, local).
Unix timestamp (seconds) at which this declaration disappeared. Omitted while present.
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /ai-governance/v1/devices/{deviceId}/plugins HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"plugins": [
{
"id": "text",
"client": "ANTIGRAVITY",
"unrecognizedClient": "text",
"marketplace": "text",
"name": "text",
"version": "text",
"status": "INSTALLED",
"trustState": "BLOCKED",
"provenance": "FIRST_PARTY",
"sourceType": "text",
"isManaged": true,
"bundledMcpCount": 1,
"bundledHookCount": 1,
"bundledAppCount": 1,
"removedAt": 1
}
],
"total": 1,
"nextPageToken": "text"
}Case-insensitive match on the hook's handler payload
An AI coding client, normalized. Endpoint agents report client names inconsistently — the same client arrives with different casing, spacing and separators depending on which config file or process reported it — so every client field and client filter on this API uses this closed vocabulary instead of the raw name.
UNKNOWN is a response value only, never a filter value: it means the reported name did not match a known client, and the raw name is then returned alongside in the accompanying unrecognizedClient field or unrecognizedClients list.
CLAUDE covers the Claude desktop app as well as the Claude client. VSCODE means Visual Studio Code itself; a Code-based product with its own identity, such as Cursor or Windsurf, reports as itself.
Filter to these hook event names. Repeatable, max 20. Matched exactly, including case.
There is no fixed vocabulary: each AI client vendor names its own lifecycle points, so the set grows as vendors add events and as new clients appear. Values observed in the field, by client — Claude Code: PreToolUse, PostToolUse, SessionStart, Stop, UserPromptSubmit, Notification, PermissionRequest. Claude: PreToolUse, PostToolUse, SessionStart, Stop, UserPromptSubmit. Codex: PreToolUse, PostToolUse, Stop, UserPromptSubmit. Copilot: PreToolUse, PostToolUse, PreCompact, SessionStart, Stop, SubagentStart, SubagentStop, UserPromptSubmit. Cursor: beforeShellExecution, afterShellExecution, beforeReadFile, afterFileEdit, afterTabFileEdit, beforeTabFileRead, beforeMCPExecution, afterMCPExecution, beforeSubmitPrompt, afterAgentResponse, afterAgentThought, preToolUse, postToolUse, postToolUseFailure, preCompact, sessionStart, sessionEnd, stop, subagentStart, subagentStop.
IMPORTANT — the same lifecycle point is spelled differently by different vendors and this filter does not normalize. Cursor uses camelCase where the others use PascalCase, so preToolUse and PreToolUse are distinct values, each matching only its own vendors' hooks. To ask "show me all pre-tool-use hooks" pass both spellings. The pairs differing only by case are preToolUse/PreToolUse, postToolUse/PostToolUse, preCompact/PreCompact, sessionStart/SessionStart, stop/Stop, subagentStart/SubagentStart and subagentStop/SubagentStop; Cursor's remaining events have no PascalCase equivalent.
Restrict to hooks declared by an MDM/enterprise-managed config file (MANAGED) or by a user-writable one (UNMANAGED). Omit to return both.
Include hooks whose declaration has disappeared from every file that declared them. Such rows carry removedAt. Defaults to false, and total moves with it. A pageToken is only valid for the filter set that produced it: changing this value (or any other filter) mid-pagination silently restarts from the first page with a freshly recomputed total, rather than returning an error.
falseSuccessful response
Opaque hook id. Use in path parameters; encodes the (client, event, handler hash) key.
An AI coding client, normalized. Endpoint agents report client names inconsistently — the same client arrives with different casing, spacing and separators depending on which config file or process reported it — so every client field and client filter on this API uses this closed vocabulary instead of the raw name.
UNKNOWN is a response value only, never a filter value: it means the reported name did not match a known client, and the raw name is then returned alongside in the accompanying unrecognizedClient field or unrecognizedClients list.
CLAUDE covers the Claude desktop app as well as the Claude client. VSCODE means Visual Studio Code itself; a Code-based product with its own identity, such as Cursor or Windsurf, reports as itself.
The reported client name, verbatim, when client is UNKNOWN. Omitted otherwise.
The agent lifecycle point the hook fires on (e.g. PreToolUse).
What the hook does — command, prompt, mcp_tool or http. The defining payload for every handler type is carried in command, which is why this field matters for interpreting it.
The hook's defining payload: the shell command for a command handler, the prompt text for a prompt handler, the tool reference or URL for the others.
Stable hash of the payload; part of the hook's identity.
Unix timestamp (seconds) at which the last file declaring this hook stopped declaring it. Omitted while it is still declared.
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /ai-governance/v1/hooks HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"hooks": [
{
"id": "text",
"client": "ANTIGRAVITY",
"unrecognizedClient": "text",
"eventName": "text",
"handlerType": "text",
"command": "text",
"commandHash": "text",
"isManaged": true,
"deviceCount": 1,
"removedAt": 1
}
],
"total": 1,
"nextPageToken": "text"
}Opaque hook id from a list response; it encodes the (client, event, handler hash) key
Match on device id, machine name, user name, or user email
Successful response
An AI coding client, normalized. Endpoint agents report client names inconsistently — the same client arrives with different casing, spacing and separators depending on which config file or process reported it — so every client field and client filter on this API uses this closed vocabulary instead of the raw name.
UNKNOWN is a response value only, never a filter value: it means the reported name did not match a known client, and the raw name is then returned alongside in the accompanying unrecognizedClient field or unrecognizedClients list.
CLAUDE covers the Claude desktop app as well as the Claude client. VSCODE means Visual Studio Code itself; a Code-based product with its own identity, such as Cursor or Windsurf, reports as itself.
The reported client name, verbatim, when client is UNKNOWN. Omitted otherwise.
What the hook is scoped to match (e.g. a tool name like Bash).
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Hook is not present on any device. Only returned for an unfiltered first page: a request carrying search or pageToken returns 200 with an empty list instead, because neither an empty filtered result nor a page past the end proves the hook is absent.
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /ai-governance/v1/hooks/{hookId}/devices HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"hook": {
"id": "text",
"client": "ANTIGRAVITY",
"unrecognizedClient": "text",
"eventName": "text",
"handlerType": "text",
"command": "text",
"commandHash": "text",
"matcher": "text"
},
"devices": [
{
"deviceId": "text",
"userEmail": "text",
"userName": "text",
"machineName": "text"
}
],
"total": 1,
"nextPageToken": "text"
}See the same parameter on /hooks.
falseSuccessful response
The same opaque hook id as the company rollup, so a caller can pivot between the two views.
An AI coding client, normalized. Endpoint agents report client names inconsistently — the same client arrives with different casing, spacing and separators depending on which config file or process reported it — so every client field and client filter on this API uses this closed vocabulary instead of the raw name.
UNKNOWN is a response value only, never a filter value: it means the reported name did not match a known client, and the raw name is then returned alongside in the accompanying unrecognizedClient field or unrecognizedClients list.
CLAUDE covers the Claude desktop app as well as the Claude client. VSCODE means Visual Studio Code itself; a Code-based product with its own identity, such as Cursor or Windsurf, reports as itself.
The reported client name, verbatim, when client is UNKNOWN. Omitted otherwise.
Unix timestamp (seconds) at which this declaration disappeared. Omitted while present.
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /ai-governance/v1/devices/{deviceId}/hooks HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"hooks": [
{
"id": "text",
"client": "ANTIGRAVITY",
"unrecognizedClient": "text",
"eventName": "text",
"handlerType": "text",
"command": "text",
"commandHash": "text",
"matcher": "text",
"isManaged": true,
"removedAt": 1
}
],
"total": 1,
"nextPageToken": "text"
}Case-insensitive match on the extension id or display name
An AI coding client, normalized. Endpoint agents report client names inconsistently — the same client arrives with different casing, spacing and separators depending on which config file or process reported it — so every client field and client filter on this API uses this closed vocabulary instead of the raw name.
UNKNOWN is a response value only, never a filter value: it means the reported name did not match a known client, and the raw name is then returned alongside in the accompanying unrecognizedClient field or unrecognizedClients list.
CLAUDE covers the Claude desktop app as well as the Claude client. VSCODE means Visual Studio Code itself; a Code-based product with its own identity, such as Cursor or Windsurf, reports as itself.
Restrict to extensions installed on this device.
Restrict to extensions classified as AI-capable.
falseSuccessful response
Opaque extension id. Use in path parameters; encodes the (extension id, version) key.
The marketplace identifier, "publisher.name".
An AI coding client, normalized. Endpoint agents report client names inconsistently — the same client arrives with different casing, spacing and separators depending on which config file or process reported it — so every client field and client filter on this API uses this closed vocabulary instead of the raw name.
UNKNOWN is a response value only, never a filter value: it means the reported name did not match a known client, and the raw name is then returned alongside in the accompanying unrecognizedClient field or unrecognizedClients list.
CLAUDE covers the Claude desktop app as well as the Claude client. VSCODE means Visual Studio Code itself; a Code-based product with its own identity, such as Cursor or Windsurf, reports as itself.
Reported names that are not a known AI client, verbatim. Omitted when empty.
True when the extension is classified as AI-capable.
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /ai-governance/v1/ide-extensions HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"extensions": [
{
"id": "text",
"extensionId": "text",
"publisher": "text",
"displayName": "text",
"version": "text",
"clients": [
"ANTIGRAVITY"
],
"unrecognizedClients": [
"text"
],
"provenance": "FIRST_PARTY",
"provenanceOverridden": true,
"isAi": true,
"deviceCount": 1
}
],
"total": 1,
"nextPageToken": "text"
}Opaque extension id from a list response; it encodes the (extension id, version) key
Successful response
Single-extension view, with the registry record and per-IDE breakdown.
Unix timestamp (seconds) of the earliest observed install.
Unix timestamp (seconds) of the most recent observation.
Whether the registry lookup succeeded. NOT_FOUND means the registry does not list this extension, which is a finding; ERROR means the registry could not be reached, which is a transient miss. Both leave provenance UNKNOWN, so this field is what distinguishes them.
An AI coding client, normalized. Endpoint agents report client names inconsistently — the same client arrives with different casing, spacing and separators depending on which config file or process reported it — so every client field and client filter on this API uses this closed vocabulary instead of the raw name.
UNKNOWN is a response value only, never a filter value: it means the reported name did not match a known client, and the raw name is then returned alongside in the accompanying unrecognizedClient field or unrecognizedClients list.
CLAUDE covers the Claude desktop app as well as the Claude client. VSCODE means Visual Studio Code itself; a Code-based product with its own identity, such as Cursor or Windsurf, reports as itself.
The reported client name, verbatim, when client is UNKNOWN. Omitted otherwise.
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Extension or version does not exist on any device
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /ai-governance/v1/ide-extensions/{extensionId} HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"id": "text",
"extensionId": "text",
"publisher": "text",
"name": "text",
"displayName": "text",
"capabilities": [
"text"
],
"provenance": "FIRST_PARTY",
"provenanceOverridden": true,
"isAi": true,
"deviceCount": 1,
"firstInstalledAt": 1,
"lastSeenAt": 1,
"registry": {
"source": "text",
"namespace": "text",
"name": "text",
"verified": true,
"deprecated": true,
"latestVersion": "text",
"lookupStatus": "OK",
"checkedAt": 1
},
"clients": [
{
"client": "ANTIGRAVITY",
"unrecognizedClient": "text",
"profiles": [
{
"profileId": "text",
"versions": [
{
"version": "text",
"provenance": "FIRST_PARTY",
"anyPrerelease": true,
"anyPinned": true,
"firstInstalledAt": 1
}
]
}
]
}
]
}Match on device id, machine name, user name, or user email
Successful response
An AI coding client, normalized. Endpoint agents report client names inconsistently — the same client arrives with different casing, spacing and separators depending on which config file or process reported it — so every client field and client filter on this API uses this closed vocabulary instead of the raw name.
UNKNOWN is a response value only, never a filter value: it means the reported name did not match a known client, and the raw name is then returned alongside in the accompanying unrecognizedClient field or unrecognizedClients list.
CLAUDE covers the Claude desktop app as well as the Claude client. VSCODE means Visual Studio Code itself; a Code-based product with its own identity, such as Cursor or Windsurf, reports as itself.
Reported names that are not a known AI client, verbatim. Omitted when empty.
Total matching devices. Only meaningful on the first page; a request carrying a pageToken does not recompute it.
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Extension or version is not installed on any device. Only returned for an unfiltered first page: a request carrying search or pageToken returns 200 with an empty list instead, because neither an empty filtered result nor a page past the end proves the extension is absent.
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /ai-governance/v1/ide-extensions/{extensionId}/devices HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"extension": {
"id": "text",
"extensionId": "text",
"publisher": "text",
"displayName": "text",
"provenance": "FIRST_PARTY"
},
"devices": [
{
"deviceId": "text",
"userEmail": "text",
"userName": "text",
"machineName": "text",
"clients": [
"ANTIGRAVITY"
],
"unrecognizedClients": [
"text"
],
"installedAt": 1
}
],
"total": 1,
"nextPageToken": "text"
}Provide a list of arbitrary string data, and scan each item with the provided detectors to uncover sensitive information. Returns a list equal in size to the number of provided string payloads. The item at each list index will be a list of all matches for the provided detectors, or an empty list if no occurrences are found.
Creates a new file upload session. If this operation returns successfully, the ID returned as part of the response object shall be used to refer to the file in all subsequent upload and scanning operations.
Upload all bytes contained in the request body to the file identified by the ID in the path parameter.
Triggers a scan of the file identified by the provided fileID. As the underlying file might be arbitrarily large, this scan is conducted asynchronously. Results from the scan are delivered to the webhook URL provided in the request payload.
List the inventory of MCP servers, aggregated per server (one row per fingerprint + version) with device counts, usage metrics, and risk.
Fetch a single MCP server by its opaque id, including registry metadata when available.
List the devices using a specific MCP server, with a per-client usage breakdown.
List devices that have any MCP server installed, aggregated per device.
Fetch a device and the full list of MCP servers running on it. The server list is returned inline and is not paginated.
List the plugin inventory, aggregated per plugin (one row per client, marketplace, name and version) with a device count and what the plugin bundles. A plugin is a governance object because of what it brings with it — MCP servers, hooks and app declarations — not merely because it is installed.
List the devices that declare a given plugin. The response also carries a small plugin-level header, so a caller deep-linking to this route can render a title without a second request.
There is no separate get-plugin endpoint, and little would be gained by one: the /plugins rollup row already carries status, trust state, provenance, description, author, repository URL and the bundled counts. The header here adds only provenanceOverridden on top of that.
List the plugins declared on a given device. Unlike the company rollup these are per-declaration rows, so they carry where the plugin came from on disk instead of a device count.
List the hook inventory, aggregated per hook (one row per client, event and handler payload) with a device count. A hook is code an AI agent runs at a lifecycle point — before a tool call, after one, on prompt submission — so it is the inventory where "what can this agent execute on my endpoint" is answered.
List the devices that declare a given hook. The response also carries a small hook-level header, so a caller deep-linking to this route can render a title without a second request.
There is no separate get-hook endpoint, and little would be gained by one: the /hooks rollup row already carries the client, event, handler type and the handler payload itself. The header here adds only matcher.
List the hooks declared on a given device. Unlike the company rollup these are per-declaration rows, so they carry which file on disk declared the hook and the matcher that scopes it — neither of which survives the rollup.
List the IDE-extension inventory, aggregated per extension and version across every IDE and device. An IDE carries hundreds of extensions and a handful of them can talk to a model, so aiOnly is usually the filter you want.
Fetch a single extension by its opaque id, including its Open VSX registry record and a per-IDE, per-profile breakdown. VS Code profiles are separate extension sets, so the same extension can be present in one profile of a machine and absent from another.
List the devices on which a given extension is installed.
Fetch a list of violations for a period
Unix timestamp in seconds, filters records created ≥ the value, defaults to -90 days UTC
Unix timestamp in seconds, filters records created < the value, defaults to end of the current day UTC
Unix timestamp in seconds, filters records updated > the value
The maximum number of records to be returned in the response
50Cursor for getting the next page of results
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
The violation id
The integration name
Unix timestamp when the violation was created
Unix timestamp when the violation was updated
The current state of the violation
The link to the resource on the integration
The channel name in case of a message in a channel
Type of location
User name
ID - user
Link to message
Members for the location
Count of members for the location
ID - channel
Name of workspace
Name of item
Type of item
Archived status
Unix timestamp
Unix timestamp
List of labels
Name of space
Key of space
Link of space
Parent page
Name of author
Email of author
Link of author name
Link to resource
ID - Confluence internal
ID - Confluence user
Version of item
ID - parent page
Version of parent page
ID of file
The name of the file
Type of file
File size
Link to file
Permissions
User list shared with - external
User list shared with - internal
Available for viewers to download
File owner
In trash
Unix timestamp, when the file was created
Unix timestamp, when the file was updated
Drive name
Updated by user
Name of project
Ticket number
Type of project
ID for the issue
Link to project
Link to ticket
Link to comment
Link to attachment
Branch on which violation occurred
Name of the organization or username in case of an individual account
Name of the repository
Email of the user who pushed the changes to GitHub
Username of the user who pushed the changes to GitHub
Unix timestamp
Boolean to check if the repo is private or public
Path of the file on which violation occurred
Permalink to the version of the file where sensitive content was identified
Owner of the repository
Link to the repository
Name of the Salesforce organization
ID of the record
Name of the object
Attachment or Object
ID of the user
Salesforce username of the author
Unix timestamp when the object was last updated
Fields of the Object
File Type
Link to the attachment
Name of the attachment
Link to the object
Status of the ticket
Title of the ticket
Ticket requested by
Group the ticket is assigned to
Agent the ticket is assigned to
User role
ID of the ticket
Followers of the ticket
Tags for the ticket
Unix timestamp
Unix timestamp
Location
Sub-location
ID - ticket comment
ID - ticket group
Link to the ticket group
ID - ticket agent
Link - ticket agent
Ticket event
Role of the user
Name of the attachment
Link for the attachment
Page creator
Page update by
Workspace name
Link to workspace
ID of the page
Title of the page
Unix timestamp
Unix timestamp
Private page link
Public page link
Externally shared state
ID of the attachment
Page URL where the extension is launched
Specific location on the page
Browser type
Remediation comment from the user
Name of the team containing the channel where the message was sent
ID of the tenant
Domain name of the tenant
ID of the team containing the channel where the message was sent
Visibility of the team containing the channel where the message was sent
Web URL of the team containing the channel where the message was sent
ID of the channel where the message was sent
Name of the channel where the message was sent
Type of the channel where the message was sent
Web URL of the channel where the message was sent
ID of the message
Unix timestamp
Unix timestamp
Sender of the chat message
ID of the user who sent the message
Principal name of the user who sent the message
ID of the attachment present in the message
Name of the attachment present in the message
URL of the attachment present in the message
Importance of the sent message
ID of the chat conversation
Type of the chat conversation (one-on-one, group, meeting)
Topic or subject of the chat conversation
ID of the user participating in the chat conversation
email address of the chat participant
display name of the chat participant
ID of the tenant
Domain name of the tenant
ID of the drive item
Name of the drive item
URL of the drive item
Mime type of the drive item
Size of the drive item in bytes
Path to the drive item relative to the root of the drive
ID of the user who created the drive item
Email of the user who last updated the drive item
ID of the user who last updated the drive item
Name of the user who last updated the drive item
Unix timestamp when the drive item was created
Unix timestamp when the drive item was last updated
Name of the special folder if drive item is inside one
ID of the drive where the drive item is present
Name of user who owns the drive where the drive item is present
Email of user who owns the drive where the drive item is present
ID of user who owns the drive where the drive item is present
Domain of the company where email was sent from
User Name who sent the email
Email of the sender
Recipients of the Email
Recipients mentioned in the CC field of the Email
Recipients mentioned in the BCC field of the Email
Subject of the email
Unix timestamp of when email was sent
ThreadID of the email
Name of the attachment
Type of attachment
The name of the file
The file mime type
The link to the resource on the integration
Policies violated
Names of the violated policies, index-aligned with policyUUIDs ("Deleted Policy" when the policy no longer exists)
Detection rules triggered
Detectors triggered
The risk label associated to this violation
The source of calculation of risk associated to this violation
The calculated score of the risk for this violation
Username as on the integration
User email as on the integration, may be empty
Next page cursor, omitted if end of results reached
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /dlp/v1/violations HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"violations": [
{
"id": "text",
"integration": "SLACK",
"createdAt": 1,
"updatedAt": 1,
"possibleActions": [
"ACKNOWLEDGE"
],
"state": "ACTIVE",
"resourceLink": "text",
"metadata": {
"slackMetadata": {
"location": "text",
"locationType": "text",
"username": "text",
"userID": "text",
"messagePermalink": "text",
"locationMembers": [
"text"
],
"locationMemberCount": 1,
"channelID": "text",
"workspaceName": "text"
},
"confluenceMetadata": {
"itemName": "text",
"itemType": "text",
"isArchived": true,
"createdAt": 1,
"updatedAt": 1,
"labels": [
"text"
],
"spaceName": "text",
"spaceKey": "text",
"spaceNameLink": "text",
"parentPageName": "text",
"authorName": "text",
"authorEmail": "text",
"authorNameLink": "text",
"permalink": "text",
"confluenceID": "text",
"confluenceUserID": "text",
"itemVersion": 1,
"parentPageID": "text",
"parentVersion": 1
},
"gdriveMetadata": {
"fileID": "text",
"fileName": "text",
"fileType": "text",
"fileSize": "text",
"fileLink": "text",
"permissionSetting": "text",
"sharingExternalUsers": [
"text"
],
"sharingInternalUsers": [
"text"
],
"canViewersDownload": true,
"fileOwner": "text",
"isInTrash": true,
"createdAt": 1,
"updatedAt": 1,
"drive": "text",
"updatedBy": "text"
},
"jiraMetadata": {
"projectName": "text",
"ticketNumber": "text",
"projectType": "text",
"issueID": "text",
"projectLink": "text",
"ticketLink": "text",
"commentLink": "text",
"attachmentLink": "text"
},
"githubMetadata": {
"branchName": "text",
"organization": "text",
"repository": "text",
"authorEmail": "text",
"authorUsername": "text",
"createdAt": 1,
"isRepoPrivate": true,
"filePath": "text",
"githubPermalink": "text",
"repositoryOwner": "text",
"githubRepoLink": "text"
},
"salesforceMetadata": {
"orgName": "text",
"recordID": "text",
"objectName": "text",
"contentType": "text",
"userID": "text",
"userName": "text",
"updatedAt": 1,
"fields": [
"text"
],
"fileType": "text",
"attachmentLink": "text",
"attachmentName": "text",
"objectLink": "text"
},
"zendeskMetadata": {
"ticketStatus": "text",
"ticketTitle": "text",
"ticketRequestor": "text",
"ticketGroupAssignee": "text",
"ticketAgentAssignee": "text",
"currentUserRole": "text",
"ticketID": 1,
"ticketFollowers": [
"text"
],
"ticketTags": "text",
"createdAt": 1,
"UpdatedAt": 1,
"location": "text",
"subLocation": "text",
"ticketCommentID": 1,
"ticketGroupID": 1,
"ticketGroupLink": "text",
"ticketAgentID": 1,
"ticketAgentLink": "text",
"ticketEvent": "text",
"userRole": "text",
"attachmentName": "text",
"attachmentLink": "text"
},
"notionMetadata": {
"createdBy": "text",
"updatedBy": "text",
"workspaceName": "text",
"workspaceLink": "text",
"pageID": "text",
"pageTitle": "text",
"createdAt": 1,
"updatedAt": 1,
"privatePageLink": "text",
"publicPageLink": "text",
"sharedExternally": true,
"attachmentID": "text"
},
"browserMetadata": {
"location": "text",
"subLocation": "text",
"browserName": "text",
"userComment": "text"
},
"m365TeamsMetadata": {
"teamName": "text",
"tenantID": "text",
"tenantDomain": "text",
"teamID": "text",
"teamVisibility": "text",
"teamWebURL": "text",
"channelID": "text",
"channelName": "text",
"channelType": "text",
"channelWebURL": "text",
"messageID": "text",
"createdAt": 1,
"updatedAt": 1,
"chatMessageSender": "text",
"userID": "text",
"userPrincipalName": "text",
"attachments": [
{
"attachmentID": "text",
"attachmentName": "text",
"attachmentURL": "text"
}
],
"chatMessageImportance": "text",
"chatID": "text",
"chatType": "text",
"chatTopic": "text",
"chatParticipants": [
{
"userID": "text",
"email": "text",
"displayName": "text"
}
]
},
"m365OnedriveMetadata": {
"tenantID": "text",
"tenantDomain": "text",
"driveItemID": "text",
"driveItemName": "text",
"driveItemURL": "text",
"driveItemMimeType": "text",
"driveItemSize": 1,
"parentPath": "text",
"createdByID": "text",
"updatedByEmail": "text",
"updatedByID": "text",
"updatedByName": "text",
"createdAt": 1,
"updatedAt": 1,
"specialFolderName": "text",
"driveID": "text",
"driveOwnerName": "text",
"driveOwnerEmail": "text",
"driveOwnerID": "text"
},
"inlineEmailMetadata": {
"domain": "text",
"user_name": "text",
"from": "text",
"to": [
"text"
],
"cc": [
"text"
],
"bcc": [
"text"
],
"subject": "text",
"sent_at": 1,
"thread_id": "text",
"attachment_name": "text",
"attachment_type": "text"
}
},
"fileDetails": {
"fileName": "text",
"mimeType": "text",
"permalink": "text"
},
"policyUUIDs": [
"text"
],
"policyNames": [
"text"
],
"detectionRuleUUIDs": [
"text"
],
"detectorUUIDs": [
"text"
],
"risk": "UNSPECIFIED",
"riskSource": "NIGHTFALL",
"riskScore": 1,
"userInfo": {
"username": "text",
"userEmail": "text"
}
}
],
"nextPageToken": "text"
}Fetch a violation by ID
The UUID of the violation to fetch
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
The violation id
The integration name
Unix timestamp when the violation was created
Unix timestamp when the violation was updated
The current state of the violation
The link to the resource on the integration
The channel name in case of a message in a channel
Type of location
User name
ID - user
Link to message
Members for the location
Count of members for the location
ID - channel
Name of workspace
Name of item
Type of item
Archived status
Unix timestamp
Unix timestamp
List of labels
Name of space
Key of space
Link of space
Parent page
Name of author
Email of author
Link of author name
Link to resource
ID - Confluence internal
ID - Confluence user
Version of item
ID - parent page
Version of parent page
ID of file
The name of the file
Type of file
File size
Link to file
Permissions
User list shared with - external
User list shared with - internal
Available for viewers to download
File owner
In trash
Unix timestamp, when the file was created
Unix timestamp, when the file was updated
Drive name
Updated by user
Name of project
Ticket number
Type of project
ID for the issue
Link to project
Link to ticket
Link to comment
Link to attachment
Branch on which violation occurred
Name of the organization or username in case of an individual account
Name of the repository
Email of the user who pushed the changes to GitHub
Username of the user who pushed the changes to GitHub
Unix timestamp
Boolean to check if the repo is private or public
Path of the file on which violation occurred
Permalink to the version of the file where sensitive content was identified
Owner of the repository
Link to the repository
Name of the Salesforce organization
ID of the record
Name of the object
Attachment or Object
ID of the user
Salesforce username of the author
Unix timestamp when the object was last updated
Fields of the Object
File Type
Link to the attachment
Name of the attachment
Link to the object
Status of the ticket
Title of the ticket
Ticket requested by
Group the ticket is assigned to
Agent the ticket is assigned to
User role
ID of the ticket
Followers of the ticket
Tags for the ticket
Unix timestamp
Unix timestamp
Location
Sub-location
ID - ticket comment
ID - ticket group
Link to the ticket group
ID - ticket agent
Link - ticket agent
Ticket event
Role of the user
Name of the attachment
Link for the attachment
Page creator
Page update by
Workspace name
Link to workspace
ID of the page
Title of the page
Unix timestamp
Unix timestamp
Private page link
Public page link
Externally shared state
ID of the attachment
Page URL where the extension is launched
Specific location on the page
Browser type
Remediation comment from the user
Name of the team containing the channel where the message was sent
ID of the tenant
Domain name of the tenant
ID of the team containing the channel where the message was sent
Visibility of the team containing the channel where the message was sent
Web URL of the team containing the channel where the message was sent
ID of the channel where the message was sent
Name of the channel where the message was sent
Type of the channel where the message was sent
Web URL of the channel where the message was sent
ID of the message
Unix timestamp
Unix timestamp
Sender of the chat message
ID of the user who sent the message
Principal name of the user who sent the message
ID of the attachment present in the message
Name of the attachment present in the message
URL of the attachment present in the message
Importance of the sent message
ID of the chat conversation
Type of the chat conversation (one-on-one, group, meeting)
Topic or subject of the chat conversation
ID of the user participating in the chat conversation
email address of the chat participant
display name of the chat participant
ID of the tenant
Domain name of the tenant
ID of the drive item
Name of the drive item
URL of the drive item
Mime type of the drive item
Size of the drive item in bytes
Path to the drive item relative to the root of the drive
ID of the user who created the drive item
Email of the user who last updated the drive item
ID of the user who last updated the drive item
Name of the user who last updated the drive item
Unix timestamp when the drive item was created
Unix timestamp when the drive item was last updated
Name of the special folder if drive item is inside one
ID of the drive where the drive item is present
Name of user who owns the drive where the drive item is present
Email of user who owns the drive where the drive item is present
ID of user who owns the drive where the drive item is present
Domain of the company where email was sent from
User Name who sent the email
Email of the sender
Recipients of the Email
Recipients mentioned in the CC field of the Email
Recipients mentioned in the BCC field of the Email
Subject of the email
Unix timestamp of when email was sent
ThreadID of the email
Name of the attachment
Type of attachment
The name of the file
The file mime type
The link to the resource on the integration
Policies violated
Names of the violated policies, index-aligned with policyUUIDs ("Deleted Policy" when the policy no longer exists)
Detection rules triggered
Detectors triggered
The risk label associated to this violation
The source of calculation of risk associated to this violation
The calculated score of the risk for this violation
Username as on the integration
User email as on the integration, may be empty
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Violation does not exist
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /dlp/v1/violations/{violationId} HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"id": "text",
"integration": "SLACK",
"createdAt": 1,
"updatedAt": 1,
"possibleActions": [
"ACKNOWLEDGE"
],
"state": "ACTIVE",
"resourceLink": "text",
"metadata": {
"slackMetadata": {
"location": "text",
"locationType": "text",
"username": "text",
"userID": "text",
"messagePermalink": "text",
"locationMembers": [
"text"
],
"locationMemberCount": 1,
"channelID": "text",
"workspaceName": "text"
},
"confluenceMetadata": {
"itemName": "text",
"itemType": "text",
"isArchived": true,
"createdAt": 1,
"updatedAt": 1,
"labels": [
"text"
],
"spaceName": "text",
"spaceKey": "text",
"spaceNameLink": "text",
"parentPageName": "text",
"authorName": "text",
"authorEmail": "text",
"authorNameLink": "text",
"permalink": "text",
"confluenceID": "text",
"confluenceUserID": "text",
"itemVersion": 1,
"parentPageID": "text",
"parentVersion": 1
},
"gdriveMetadata": {
"fileID": "text",
"fileName": "text",
"fileType": "text",
"fileSize": "text",
"fileLink": "text",
"permissionSetting": "text",
"sharingExternalUsers": [
"text"
],
"sharingInternalUsers": [
"text"
],
"canViewersDownload": true,
"fileOwner": "text",
"isInTrash": true,
"createdAt": 1,
"updatedAt": 1,
"drive": "text",
"updatedBy": "text"
},
"jiraMetadata": {
"projectName": "text",
"ticketNumber": "text",
"projectType": "text",
"issueID": "text",
"projectLink": "text",
"ticketLink": "text",
"commentLink": "text",
"attachmentLink": "text"
},
"githubMetadata": {
"branchName": "text",
"organization": "text",
"repository": "text",
"authorEmail": "text",
"authorUsername": "text",
"createdAt": 1,
"isRepoPrivate": true,
"filePath": "text",
"githubPermalink": "text",
"repositoryOwner": "text",
"githubRepoLink": "text"
},
"salesforceMetadata": {
"orgName": "text",
"recordID": "text",
"objectName": "text",
"contentType": "text",
"userID": "text",
"userName": "text",
"updatedAt": 1,
"fields": [
"text"
],
"fileType": "text",
"attachmentLink": "text",
"attachmentName": "text",
"objectLink": "text"
},
"zendeskMetadata": {
"ticketStatus": "text",
"ticketTitle": "text",
"ticketRequestor": "text",
"ticketGroupAssignee": "text",
"ticketAgentAssignee": "text",
"currentUserRole": "text",
"ticketID": 1,
"ticketFollowers": [
"text"
],
"ticketTags": "text",
"createdAt": 1,
"UpdatedAt": 1,
"location": "text",
"subLocation": "text",
"ticketCommentID": 1,
"ticketGroupID": 1,
"ticketGroupLink": "text",
"ticketAgentID": 1,
"ticketAgentLink": "text",
"ticketEvent": "text",
"userRole": "text",
"attachmentName": "text",
"attachmentLink": "text"
},
"notionMetadata": {
"createdBy": "text",
"updatedBy": "text",
"workspaceName": "text",
"workspaceLink": "text",
"pageID": "text",
"pageTitle": "text",
"createdAt": 1,
"updatedAt": 1,
"privatePageLink": "text",
"publicPageLink": "text",
"sharedExternally": true,
"attachmentID": "text"
},
"browserMetadata": {
"location": "text",
"subLocation": "text",
"browserName": "text",
"userComment": "text"
},
"m365TeamsMetadata": {
"teamName": "text",
"tenantID": "text",
"tenantDomain": "text",
"teamID": "text",
"teamVisibility": "text",
"teamWebURL": "text",
"channelID": "text",
"channelName": "text",
"channelType": "text",
"channelWebURL": "text",
"messageID": "text",
"createdAt": 1,
"updatedAt": 1,
"chatMessageSender": "text",
"userID": "text",
"userPrincipalName": "text",
"attachments": [
{
"attachmentID": "text",
"attachmentName": "text",
"attachmentURL": "text"
}
],
"chatMessageImportance": "text",
"chatID": "text",
"chatType": "text",
"chatTopic": "text",
"chatParticipants": [
{
"userID": "text",
"email": "text",
"displayName": "text"
}
]
},
"m365OnedriveMetadata": {
"tenantID": "text",
"tenantDomain": "text",
"driveItemID": "text",
"driveItemName": "text",
"driveItemURL": "text",
"driveItemMimeType": "text",
"driveItemSize": 1,
"parentPath": "text",
"createdByID": "text",
"updatedByEmail": "text",
"updatedByID": "text",
"updatedByName": "text",
"createdAt": 1,
"updatedAt": 1,
"specialFolderName": "text",
"driveID": "text",
"driveOwnerName": "text",
"driveOwnerEmail": "text",
"driveOwnerID": "text"
},
"inlineEmailMetadata": {
"domain": "text",
"user_name": "text",
"from": "text",
"to": [
"text"
],
"cc": [
"text"
],
"bcc": [
"text"
],
"subject": "text",
"sent_at": 1,
"thread_id": "text",
"attachment_name": "text",
"attachment_type": "text"
}
},
"fileDetails": {
"fileName": "text",
"mimeType": "text",
"permalink": "text"
},
"policyUUIDs": [
"text"
],
"policyNames": [
"text"
],
"detectionRuleUUIDs": [
"text"
],
"detectorUUIDs": [
"text"
],
"risk": "UNSPECIFIED",
"riskSource": "NIGHTFALL",
"riskScore": 1,
"userInfo": {
"username": "text",
"userEmail": "text"
}
}Fetch a list of violations based on some filters
Unix timestamp in seconds, filters records created ≥ the value, defaults to -90 days UTC
Unix timestamp in seconds, filters records created < the value, defaults to end of the current day UTC
Unix timestamp in seconds, filters records updated > the value
The maximum number of records to be returned in the response
50Cursor for getting the next page of results
Sort key and direction, defaults to descending order by creation time
TIME_DESCPossible values: The query containing filter clauses
Query structure and terminology
A query clause consists of a field followed by an operator followed by a value:
| term | value |
|---|---|
| clause | user_email:"amy@rocketrides.io" |
| field | user_email |
| operator | : |
| value | amy@rocketrides.io |
You can combine multiple query clauses in a search by separating them with a space.
Field types, substring matching, and numeric comparators
Every search field supports exact matching with a :. Certain fields such as user_email and user_name support substring matching.
Quotes
You may use quotation marks around string values. Quotation marks are required in case the value contains spaces. For example:
user_mail:john@example.comuser_name:"John Doe"Special Characters
+ - && || ! ( ) { } [ ] ^ " ~ * ? : are special characters need to be escaped using \. For example:
(1+1):2 should be searched for using \(1\+1)\:2Search Syntax
The following table lists the syntax that you can use to construct a query.
| SYNTAX | USAGE | DESCRIPTION | EXAMPLES |
|---|---|---|---|
: | field:value | Exact match operator (case insensitive) | state:"pending" returns records where the currency is exactly "PENDING" in a case-insensitive comparison |
(space) | field1:value1 field2:value2 | The query returns only records that match both clauses | state:active slack.channel_name:general |
OR | field:(value1 OR value2) | The query returns records that match either of the values (case insensitive) | state:(active OR pending) |
Query Fields
| param | description |
|---|---|
| state | the violation states to filter on |
| user_email | the emails of users updating the resource resulting in the violation |
| user_name | the usernames of users updating the resource resulting in the violation |
| integration_name | the integration to filter on |
| confidence | one or more likelihoods/confidences |
| policy_id | one or more policy IDs |
| detection_rule_id | one or more detection rule IDs |
| detector_id | one or more detector IDs |
| risk_label | the risk label to filter on |
| risk_source | the risk determination source to filter on |
| slack.channel_name | the slack channel names to filter on |
| slack.channel_id | the slack channel IDs to filter on |
| slack.workspace | the slack workspaces to filter on |
| confluence.parent_page_name | the names of the parent pages in confluence to filter on |
| confluence.space_name | the names of the spaces in confluence to filter on |
| gdrive.drive | the drive names in gdrive to filter on |
| jira.project_name | the jira project names to filter on |
| jira.ticket_number | the jira ticket numbers to filter on |
| salesforce.org_name | the salesforce organization names to filter on |
| salesforce.object | the salesforce object names to filter on |
| salesforce.record_id | the salesforce record IDs to filter on |
| github.author_email | the github author emails to filter on |
| github.branch | the github branches to filter on |
| github.commit | the github commit ids to filter on |
| github.org | the github organizations to filter on |
| github.repository | the github repositories to filter on |
| github.repository_owner | the github repository owners to filter on |
| teams.team_name | the m365 teams team names to filter on |
| teams.channel_name | the m365 teams channels to filter on |
| teams.channel_type | the m365 teams channel types to filter on |
| teams.team_sensitivity | the m365 teams sensitivities to filter on |
| teams.sender | the m365 teams senders to filter on |
| teams.msg_importance | the m365 teams importance to filter on |
| teams.msg_attachment | the m365 teams attachment names to filter on |
| teams.chat_id | the m365 teams chat ID to filter on |
| teams.chat_type | the m365 teams chat type to filter on |
| teams.chat_topic | the m365 teams chat topic to filter on |
| teams.chat_participant | the m365 teams chat participant's display name to filter on |
| onedrive.drive_owner | drive owner's display name to filter on |
| onedrive.drive_owner_email | drive owner's email to filter on |
| onedrive.file_name | the file name to filter on |
| onedrive.created_by | the m365 user, who created the file in the drive, display name to filter on |
| onedrive.created_by_email | the m365 users, who created the file in the drive, email to filter on |
| onedrive.modified_by | the m365 users, who last modified the file in the drive, display name to filter on |
| onedrive.modified_by_email | the m365 users, who last modified the file in the drive, email to filter on |
| zendesk.ticket_status | the zendesk ticket status to filter on |
| zendesk.ticket_title | the zendesk ticket titles to filter on |
| zendesk.ticket_group_assignee | the zendesk ticket assignee groups to filter on |
| zendesk.current_user_role | the zendesk ticket current assignee user's roles to filter on |
| notion.created_by | the names of the users creating a resource in notion to filter on |
| notion.last_edited_by | the names of the users editing a resource in notion to filter on |
| notion.page_title | the page names in notion to filter on |
| notion.workspace_name | the workspace names in notion to filter on |
| gmail.user_name | the names of the sender to filter on |
| gmail.from | the email of sender to filter on |
| gmail.to | the email or name of recipients to filter on |
| gmail.cc | the email or name of cc to filter on |
| gmail.bcc | the email or name of bcc to filter on |
| gmail.thread_id | the thread id of email to filter on |
| gmail.subject | the subject of email to filter on |
| gmail.attachment_name | the name of attachment to filter on |
| gmail.attachment_type | the type of attachment to filter on |
| last_actioned_by | the entity that performed the last action on the violation, can be one of NIGHTFALL, ADMIN or END_USER |
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
The violation id
The integration name
Unix timestamp when the violation was created
Unix timestamp when the violation was updated
The current state of the violation
The link to the resource on the integration
The channel name in case of a message in a channel
Type of location
User name
ID - user
Link to message
Members for the location
Count of members for the location
ID - channel
Name of workspace
Name of item
Type of item
Archived status
Unix timestamp
Unix timestamp
List of labels
Name of space
Key of space
Link of space
Parent page
Name of author
Email of author
Link of author name
Link to resource
ID - Confluence internal
ID - Confluence user
Version of item
ID - parent page
Version of parent page
ID of file
The name of the file
Type of file
File size
Link to file
Permissions
User list shared with - external
User list shared with - internal
Available for viewers to download
File owner
In trash
Unix timestamp, when the file was created
Unix timestamp, when the file was updated
Drive name
Updated by user
Name of project
Ticket number
Type of project
ID for the issue
Link to project
Link to ticket
Link to comment
Link to attachment
Branch on which violation occurred
Name of the organization or username in case of an individual account
Name of the repository
Email of the user who pushed the changes to GitHub
Username of the user who pushed the changes to GitHub
Unix timestamp
Boolean to check if the repo is private or public
Path of the file on which violation occurred
Permalink to the version of the file where sensitive content was identified
Owner of the repository
Link to the repository
Name of the Salesforce organization
ID of the record
Name of the object
Attachment or Object
ID of the user
Salesforce username of the author
Unix timestamp when the object was last updated
Fields of the Object
File Type
Link to the attachment
Name of the attachment
Link to the object
Status of the ticket
Title of the ticket
Ticket requested by
Group the ticket is assigned to
Agent the ticket is assigned to
User role
ID of the ticket
Followers of the ticket
Tags for the ticket
Unix timestamp
Unix timestamp
Location
Sub-location
ID - ticket comment
ID - ticket group
Link to the ticket group
ID - ticket agent
Link - ticket agent
Ticket event
Role of the user
Name of the attachment
Link for the attachment
Page creator
Page update by
Workspace name
Link to workspace
ID of the page
Title of the page
Unix timestamp
Unix timestamp
Private page link
Public page link
Externally shared state
ID of the attachment
Page URL where the extension is launched
Specific location on the page
Browser type
Remediation comment from the user
Name of the team containing the channel where the message was sent
ID of the tenant
Domain name of the tenant
ID of the team containing the channel where the message was sent
Visibility of the team containing the channel where the message was sent
Web URL of the team containing the channel where the message was sent
ID of the channel where the message was sent
Name of the channel where the message was sent
Type of the channel where the message was sent
Web URL of the channel where the message was sent
ID of the message
Unix timestamp
Unix timestamp
Sender of the chat message
ID of the user who sent the message
Principal name of the user who sent the message
ID of the attachment present in the message
Name of the attachment present in the message
URL of the attachment present in the message
Importance of the sent message
ID of the chat conversation
Type of the chat conversation (one-on-one, group, meeting)
Topic or subject of the chat conversation
ID of the user participating in the chat conversation
email address of the chat participant
display name of the chat participant
ID of the tenant
Domain name of the tenant
ID of the drive item
Name of the drive item
URL of the drive item
Mime type of the drive item
Size of the drive item in bytes
Path to the drive item relative to the root of the drive
ID of the user who created the drive item
Email of the user who last updated the drive item
ID of the user who last updated the drive item
Name of the user who last updated the drive item
Unix timestamp when the drive item was created
Unix timestamp when the drive item was last updated
Name of the special folder if drive item is inside one
ID of the drive where the drive item is present
Name of user who owns the drive where the drive item is present
Email of user who owns the drive where the drive item is present
ID of user who owns the drive where the drive item is present
Domain of the company where email was sent from
User Name who sent the email
Email of the sender
Recipients of the Email
Recipients mentioned in the CC field of the Email
Recipients mentioned in the BCC field of the Email
Subject of the email
Unix timestamp of when email was sent
ThreadID of the email
Name of the attachment
Type of attachment
The name of the file
The file mime type
The link to the resource on the integration
Policies violated
Names of the violated policies, index-aligned with policyUUIDs ("Deleted Policy" when the policy no longer exists)
Detection rules triggered
Detectors triggered
The risk label associated to this violation
The source of calculation of risk associated to this violation
The calculated score of the risk for this violation
Username as on the integration
User email as on the integration, may be empty
Next page cursor, omitted if end of results reached
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /dlp/v1/violations/search?query=text HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"violations": [
{
"id": "text",
"integration": "SLACK",
"createdAt": 1,
"updatedAt": 1,
"possibleActions": [
"ACKNOWLEDGE"
],
"state": "ACTIVE",
"resourceLink": "text",
"metadata": {
"slackMetadata": {
"location": "text",
"locationType": "text",
"username": "text",
"userID": "text",
"messagePermalink": "text",
"locationMembers": [
"text"
],
"locationMemberCount": 1,
"channelID": "text",
"workspaceName": "text"
},
"confluenceMetadata": {
"itemName": "text",
"itemType": "text",
"isArchived": true,
"createdAt": 1,
"updatedAt": 1,
"labels": [
"text"
],
"spaceName": "text",
"spaceKey": "text",
"spaceNameLink": "text",
"parentPageName": "text",
"authorName": "text",
"authorEmail": "text",
"authorNameLink": "text",
"permalink": "text",
"confluenceID": "text",
"confluenceUserID": "text",
"itemVersion": 1,
"parentPageID": "text",
"parentVersion": 1
},
"gdriveMetadata": {
"fileID": "text",
"fileName": "text",
"fileType": "text",
"fileSize": "text",
"fileLink": "text",
"permissionSetting": "text",
"sharingExternalUsers": [
"text"
],
"sharingInternalUsers": [
"text"
],
"canViewersDownload": true,
"fileOwner": "text",
"isInTrash": true,
"createdAt": 1,
"updatedAt": 1,
"drive": "text",
"updatedBy": "text"
},
"jiraMetadata": {
"projectName": "text",
"ticketNumber": "text",
"projectType": "text",
"issueID": "text",
"projectLink": "text",
"ticketLink": "text",
"commentLink": "text",
"attachmentLink": "text"
},
"githubMetadata": {
"branchName": "text",
"organization": "text",
"repository": "text",
"authorEmail": "text",
"authorUsername": "text",
"createdAt": 1,
"isRepoPrivate": true,
"filePath": "text",
"githubPermalink": "text",
"repositoryOwner": "text",
"githubRepoLink": "text"
},
"salesforceMetadata": {
"orgName": "text",
"recordID": "text",
"objectName": "text",
"contentType": "text",
"userID": "text",
"userName": "text",
"updatedAt": 1,
"fields": [
"text"
],
"fileType": "text",
"attachmentLink": "text",
"attachmentName": "text",
"objectLink": "text"
},
"zendeskMetadata": {
"ticketStatus": "text",
"ticketTitle": "text",
"ticketRequestor": "text",
"ticketGroupAssignee": "text",
"ticketAgentAssignee": "text",
"currentUserRole": "text",
"ticketID": 1,
"ticketFollowers": [
"text"
],
"ticketTags": "text",
"createdAt": 1,
"UpdatedAt": 1,
"location": "text",
"subLocation": "text",
"ticketCommentID": 1,
"ticketGroupID": 1,
"ticketGroupLink": "text",
"ticketAgentID": 1,
"ticketAgentLink": "text",
"ticketEvent": "text",
"userRole": "text",
"attachmentName": "text",
"attachmentLink": "text"
},
"notionMetadata": {
"createdBy": "text",
"updatedBy": "text",
"workspaceName": "text",
"workspaceLink": "text",
"pageID": "text",
"pageTitle": "text",
"createdAt": 1,
"updatedAt": 1,
"privatePageLink": "text",
"publicPageLink": "text",
"sharedExternally": true,
"attachmentID": "text"
},
"browserMetadata": {
"location": "text",
"subLocation": "text",
"browserName": "text",
"userComment": "text"
},
"m365TeamsMetadata": {
"teamName": "text",
"tenantID": "text",
"tenantDomain": "text",
"teamID": "text",
"teamVisibility": "text",
"teamWebURL": "text",
"channelID": "text",
"channelName": "text",
"channelType": "text",
"channelWebURL": "text",
"messageID": "text",
"createdAt": 1,
"updatedAt": 1,
"chatMessageSender": "text",
"userID": "text",
"userPrincipalName": "text",
"attachments": [
{
"attachmentID": "text",
"attachmentName": "text",
"attachmentURL": "text"
}
],
"chatMessageImportance": "text",
"chatID": "text",
"chatType": "text",
"chatTopic": "text",
"chatParticipants": [
{
"userID": "text",
"email": "text",
"displayName": "text"
}
]
},
"m365OnedriveMetadata": {
"tenantID": "text",
"tenantDomain": "text",
"driveItemID": "text",
"driveItemName": "text",
"driveItemURL": "text",
"driveItemMimeType": "text",
"driveItemSize": 1,
"parentPath": "text",
"createdByID": "text",
"updatedByEmail": "text",
"updatedByID": "text",
"updatedByName": "text",
"createdAt": 1,
"updatedAt": 1,
"specialFolderName": "text",
"driveID": "text",
"driveOwnerName": "text",
"driveOwnerEmail": "text",
"driveOwnerID": "text"
},
"inlineEmailMetadata": {
"domain": "text",
"user_name": "text",
"from": "text",
"to": [
"text"
],
"cc": [
"text"
],
"bcc": [
"text"
],
"subject": "text",
"sent_at": 1,
"thread_id": "text",
"attachment_name": "text",
"attachment_type": "text"
}
},
"fileDetails": {
"fileName": "text",
"mimeType": "text",
"permalink": "text"
},
"policyUUIDs": [
"text"
],
"policyNames": [
"text"
],
"detectionRuleUUIDs": [
"text"
],
"detectorUUIDs": [
"text"
],
"risk": "UNSPECIFIED",
"riskSource": "NIGHTFALL",
"riskScore": 1,
"userInfo": {
"username": "text",
"userEmail": "text"
}
}
],
"nextPageToken": "text"
}Get findings for a specific violation
The UUID of the violation
Cursor for getting the next page of results
Number of findings to fetch in one page (max 1000)
1000Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
The id of the findings
The id of the detector that was triggered
The sub detector id in case the detector uses a combination of detectors
The likelihood of the detection
The redacted sensitive data
Data preceding the sensitive data
Data after the sensitive data
Start point for a range
End point for a range
Start point for a range
End point for a range
Key status
Key type
Additional details about the key
Metadata/sub-location of the finding in the resource. For example - title or description for a Jira ticket.
The annotation id, if present
Next page cursor, omitted if end of results reached
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Violation does not exist
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /dlp/v1/violations/{violationId}/findings HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"findings": [
{
"id": "text",
"detectorUUID": "text",
"subDetectorUUID": "text",
"confidence": "text",
"redactedSensitiveText": "text",
"redactedContext": {
"beforeContext": "text",
"afterContext": "text"
},
"redactedLocation": {
"byteRange": {
"start": 1,
"end": 1
},
"lineRange": {
"start": 1,
"end": 1
}
},
"metadata": {
"apiKeyMetaData": {
"status": "UNVERIFIED",
"kind": "UNSPECIFIED",
"description": "text"
}
},
"subLocation": "text",
"annotationUUID": "text"
}
],
"nextPageToken": "text"
}Perform an action on a list of violations. If an action can't be performed on a violation, that violation is ignored. Depending on the action, it could be processed immediately or queued.
The UUIDs of the violations to perform the action on
The action to perform on the violations
Successful response (processed immediately)
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
violation UUIDs that were processed
Accepted response (queued for processing)
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
violation UUIDs that were queued for processing
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
POST /dlp/v1/violations/actions HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 82
{
"violationUUIDs": [
"123e4567-e89b-12d3-a456-426614174000"
],
"action": "ACKNOWLEDGE"
}{
"submitted": [
"123e4567-e89b-12d3-a456-426614174000"
]
}Fetch an annotation by ID
The UUID of the annotation to fetch
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
The annotation id
The annotation type
The annotation comment
Whether the annotation applies to all findings of this sensitive data
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Annotation does not exist
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /dlp/v1/annotations/{annotationId} HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"type": "DETECTOR_FALSE_POSITIVE",
"comment": "text",
"autoApply": true
}Annotate a finding
The UUID of the finding to annotate
The annotation type
The comment to add to the annotation
Whether the annotation applies to all findings of this sensitive data (defaults to true)
trueSuccessful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
The annotation id
The annotation type
The annotation comment
Whether the annotation applies to all findings of this sensitive data
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Finding already annotated
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
POST /dlp/v1/findings/{findingId}/annotate HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 68
{
"type": "DETECTOR_FALSE_POSITIVE",
"comment": "text",
"autoApply": true
}{
"id": "123e4567-e89b-12d3-a456-426614174000",
"type": "DETECTOR_FALSE_POSITIVE",
"comment": "text",
"autoApply": true
}Remove the annotation for a finding
The UUID of the finding to unannotate
Successful response (even if annotation does not exist)
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
POST /dlp/v1/findings/{findingId}/unannotate HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
No content
Fetch the activity feed for a specific violation
The UUID of the violation
Number of activity items to fetch in one page
50Unix timestamp in seconds, filters activity created > the value
Unix timestamp in seconds, filters activity created < the value
Whether to sort results in descending order (default false)
falseCursor for getting the next page of results
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
Unique identifier for the activity log entry
Human-readable message describing the activity
Unix timestamp in seconds when the activity occurred
Next page cursor, omitted if end of results reached
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Violation does not exist
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /dlp/v1/violations/{violationId}/activity HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"activities": [
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"message": "text",
"timestamp": 1,
"type": "CREATION",
"data": {
"action": "ACKNOWLEDGE",
"userUUID": "123e4567-e89b-12d3-a456-426614174000",
"userName": "text",
"userEmail": "text",
"receiverEmail": "text",
"actionLogData": {
"applyLabelsActionLogData": {
"activityType": "LABELS_SUCCESSFULLY_APPLIED",
"labels": [
"text"
],
"labelUpdatesOnResource": {
"ANY_ADDITIONAL_PROPERTY": "text"
},
"failureReason": "text"
},
"setExpirationActionLogData": {
"expirationTime": 1
},
"revokeAccessActionLogData": {
"revokedEmails": [
"text"
],
"unRevokedEmails": [
"text"
]
},
"notifyEmailActionLogData": {
"receiverEmail": "text"
},
"genericActionLogData": {
"additionalContext": "text"
},
"blockActionActionLogData": {
"isBlocked": true,
"blockReason": "text",
"skippedReason": "text"
}
}
}
}
],
"nextPageToken": "text"
}Fetch a list of exfiltration events based on some filters
Unix timestamp in seconds, filters records created ≥ the value, defaults to -180 days UTC
Unix timestamp in seconds, filters records created < the value, defaults to end of the current day UTC
Unix timestamp in seconds, filters records updated > the value
The maximum number of records to be returned in the response
50Cursor for getting the next page of results
Sort key and direction, defaults to descending order by creation time
TIME_DESCPossible values: The query containing filter clauses
Query structure and terminology
A query clause consists of a field followed by an operator followed by a value:
| term | value |
|---|---|
| clause | user_email:"amy@rocketrides.io" |
| field | user_email |
| operator | : |
| value | amy@rocketrides.io |
You can combine multiple query clauses in a search by separating them with a space.
Field types, substring matching, and numeric comparators
Every search field supports exact matching with a :. Certain fields such as user_email and user_name support substring matching.
Quotes
You may use quotation marks around string values. Quotation marks are required in case the value contains spaces. For example:
user_mail:john@example.comuser_name:"John Doe"Special Characters
+ - && || ! ( ) { } [ ] ^ " ~ * ? : are special characters need to be escaped using \. For example:
(1+1):2 should be searched for using \(1\+1)\:2Search Syntax
The following table lists the syntax that you can use to construct a query.
| SYNTAX | USAGE | DESCRIPTION | EXAMPLES |
|---|---|---|---|
: | field:value | Exact match operator (case insensitive) | state:"pending" returns records where the currency is exactly "PENDING" in a case-insensitive comparison |
(space) | field1:value1 field2:value2 | The query returns only records that match both clauses | state:active slack.channel_name:general |
OR | field:(value1 OR value2) | The query returns records that match either of the values (case insensitive) | state:(active OR pending) |
Query Fields
| param | description |
|---|---|
| event_id | the unique identifier of the exfiltration event to filter on |
| integration_name | the name of the integration to filter on |
| state | the state of the event to filter on (active, pending, resolved, expired) |
| event_type | the type of exfiltration event to filter on |
| actor_name | the name of the actor who performed the action to filter on |
| actor_email | the email of the actor who performed the action to filter on |
| user_name | the username of the user to filter on (backward compatibility) |
| user_email | the email of the user to filter on (backward compatibility) |
| notes | the comment or notes associated with the event to filter on |
| risk_label | the risk label to filter on |
| risk_source | the risk determination source to filter on |
| policy_id | the unique identifier of the policy to filter on |
| policy_name | the name of the policy to filter on |
| resource_id | the identifier of the resource to filter on |
| resource_name | the name of the resource to filter on |
| resource_owner_name | the name of the resource owner to filter on |
| resource_owner_email | the email of the resource owner to filter on |
| resource_content_type | the content type of the resource to filter on |
| endpoint.device_id | the device identifier for endpoint events to filter on |
| endpoint.machine_name | the machine name for endpoint events to filter on |
| endpoint.ai_agent.client_type | the AI agent client (e.g. claude_code, cursor, cowork) to filter on |
| endpoint.ai_agent.client_version | the AI agent client version to filter on |
| endpoint.ai_agent.trigger_point | the AI agent event phase (PROMPT, MODEL_RESPONSE, TOOL_REQUEST, TOOL_RESPONSE, SHELL, OTEL_TELEMETRY) to filter on |
| endpoint.ai_agent.session_id | the AI agent session identifier to filter on |
| endpoint.ai_agent.tool_name | the tool invoked by the AI agent to filter on |
| endpoint.ai_agent.server_name | the MCP server that served the tool to filter on |
| endpoint.ai_agent.decision | the permission decision (allow, deny, ask) to filter on |
| endpoint.ai_agent.tool_use_id | the unique identifier for a specific tool invocation to filter on |
| endpoint.ai_agent.model | the model used for the request (OTel only, e.g. claude-opus-4-7) to filter on |
| endpoint.ai_agent.error_message | the error message from a failed AI agent call to filter on |
| gdrive.permission | the permission setting for Google Drive files to filter on |
| gdrive.shared_internal_email | the internal emails with which the file is shared to filter on |
| gdrive.shared_external_email | the external emails with which the file is shared to filter on |
| gdrive.drive | the Google Drive name to filter on |
| gdrive.file_owner | the owner of the Google Drive file to filter on |
| gdrive.label_name | the label name applied to Google Drive files to filter on |
| salesforce.report.scope | the scope of the Salesforce report to filter on |
| salesforce.report.event_source | the event source of the Salesforce report to filter on |
| salesforce.report.source_ip | the source IP address of the Salesforce report to filter on |
| salesforce.report.session_level | the session level of the Salesforce report to filter on |
| salesforce.report.operation | the operation type of the Salesforce report to filter on |
| salesforce.report.description | the description of the Salesforce report to filter on |
| salesforce.file.source_ip | the source IP address for Salesforce file events to filter on |
| salesforce.file.session_level | the session level for Salesforce file events to filter on |
| last_actioned_by | the entity that performed the last action on the violation, can be one of NIGHTFALL, ADMIN or END_USER |
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
Unique identifier for the exfiltration event
Integration type that generated the event (e.g., GDRIVE, ES_WINDOWS, ES_MAC)
Unix timestamp in seconds indicating when the event was created
Current state of the event (e.g., ACTIVE, RESOLVED, EXPIRED, PENDING)
Type of exfiltration event (e.g., DOWNLOAD, ENDPOINTDLP_BROWSER_UPLOAD)
List of policy UUIDs that triggered the event
Names of the policies that triggered the event, index-aligned with policyUUIDs ("Deleted Policy" when the policy no longer exists)
Number of assets involved in the exfiltration event
Username of the associated user
Email of the associated user
Link to the user's profile
Device identifier for endpoint events
Machine name for endpoint events
Whether the user is external to the organization
Identifier of the application
Name of the application
The risk label associated to this event
The source of calculation of risk associated to this event
The calculated score of the risk for this event
Next page cursor, omitted if end of results reached
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /exfiltration/v1/events/search?query=text HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"events": [
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"integration": "text",
"createdAt": 1,
"state": "text",
"eventType": "text",
"policyUUIDs": [
"123e4567-e89b-12d3-a456-426614174000"
],
"policyNames": [
"text"
],
"assetsCount": 1,
"userInfo": {
"username": "text",
"userEmail": "name@gmail.com",
"userProfileLink": "https://example.com",
"deviceId": "text",
"machineName": "text",
"isExternal": true
},
"appInfo": {
"id": "text",
"name": "text"
},
"risk": "UNSPECIFIED",
"riskSource": "NIGHTFALL",
"riskScore": 1
}
],
"nextPageToken": "text"
}Fetch a list of exfiltration events for a period
Unix timestamp in seconds, filters records created ≥ the value, defaults to -90 days UTC
Unix timestamp in seconds, filters records created < the value, defaults to end of the current day UTC
Unix timestamp in seconds, filters records updated > the value
The maximum number of records to be returned in the response
50Cursor for getting the next page of results
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
Unique identifier for the exfiltration event
Integration type that generated the event (e.g., GDRIVE, ES_WINDOWS, ES_MAC)
Unix timestamp in seconds indicating when the event was created
Current state of the event (e.g., ACTIVE, RESOLVED, EXPIRED, PENDING)
Type of exfiltration event (e.g., DOWNLOAD, ENDPOINTDLP_BROWSER_UPLOAD)
List of policy UUIDs that triggered the event
Names of the policies that triggered the event, index-aligned with policyUUIDs ("Deleted Policy" when the policy no longer exists)
Number of assets involved in the exfiltration event
Username of the associated user
Email of the associated user
Link to the user's profile
Device identifier for endpoint events
Machine name for endpoint events
Whether the user is external to the organization
Identifier of the application
Name of the application
The risk label associated to this event
The source of calculation of risk associated to this event
The calculated score of the risk for this event
Next page cursor, omitted if end of results reached
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /exfiltration/v1/events HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"events": [
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"integration": "text",
"createdAt": 1,
"state": "text",
"eventType": "text",
"policyUUIDs": [
"123e4567-e89b-12d3-a456-426614174000"
],
"policyNames": [
"text"
],
"assetsCount": 1,
"userInfo": {
"username": "text",
"userEmail": "name@gmail.com",
"userProfileLink": "https://example.com",
"deviceId": "text",
"machineName": "text",
"isExternal": true
},
"appInfo": {
"id": "text",
"name": "text"
},
"risk": "UNSPECIFIED",
"riskSource": "NIGHTFALL",
"riskScore": 1
}
],
"nextPageToken": "text"
}Fetch an exfiltration event details by ID
The UUID of the event to fetch
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
Unique identifier for the exfiltration event (the violation UUID; matches the id returned by list/search and the :eventUUID path parameter)
List of policy UUIDs that triggered the event
Names of the policies that triggered the event, index-aligned with policyUUIDs ("Deleted Policy" when the policy no longer exists)
Unique identifier for the asset
Name of the asset
Path to the asset
Size of the asset in bytes
MIME type of the asset
Unique identifier for the actor in Nightfall
Email of the actor
Comment or notes associated with the event
Groups the user belongs to
Whether the user is an admin
Whether the user is suspended
Timestamp when the user was created
Salesforce user metadata (currently empty as per spec)
ID of the device
Name of the machine/device
Comment or notes associated with the asset
DDR violations IDs associated with the resource
ID of the file
Name of the file
Size of the file
Link to the file
Permission setting for the file
External users with whom the file is shared
Internal users with whom the file is shared
Whether viewers can download the file
Owner of the file
Whether the file is in trash
Timestamp when the file was created
Timestamp when the file was last updated
Drive where the file is located
Labels associated with the file
Type of file permission
Type of Salesforce resource
Action performed on the file
Source IP address
Level of the session
Description of the report
Entity fields displayed in the report
Name of the dashboard
Scope of the report
Operation performed
Number of records
Entities queried in the report
Grouped column headers
Number of columns
Number of rows processed
Source IP address
Source of the event
Level of the session
Query executed
Identifier of the event
Source IP address
Key of the session
Level of the session
Medium used
Name of the medium
User of the endpoint agent
Unique identifier for the actor in Nightfall
Email of the actor
Comment or notes associated with the event
Groups the user belongs to
Whether the user is an admin
Whether the user is suspended
Timestamp when the user was created
Salesforce user metadata (currently empty as per spec)
ID of the device
Name of the machine/device
Type of the event
Timestamp of the event
Name of the browser
Version of the browser
Domain where the upload occurred
URL of the active browser tab
Title of the active browser tab
Unix timestamp in milliseconds when the upload started
Unix timestamp in milliseconds when the upload ended
Name of the uploaded file
Unix timestamp of the origin event
Name of the browser
Version of the browser
Domain where the download occurred
URL of the browser tab
Title of the browser tab
Unix timestamp when the download started
Unix timestamp when the download ended
Type of content copied to clipboard
Name of the browser
Version of the browser
Domain of the browser
URL of the browser tab
Title of the browser tab
Cloud sync application
Type of account
Name of the account
Email associated with the account
Path where the file was synced
Unix timestamp in milliseconds when the upload started
Unix timestamp in milliseconds when the upload ended
Name of the synced file
Type of content in the clipboard
Type of app the content was pasted into (e.g. CAT_BROWSER, CAT_THICK_APP, CAT_GENERIC_APP)
Unix timestamp of the origin event
Name of the browser
Version of the browser
Domain where the download occurred
URL of the browser tab
Title of the browser tab
Unix timestamp when the download started
Unix timestamp when the download ended
Type of content copied to clipboard
Name of the browser
Version of the browser
Domain of the browser
URL of the browser tab
Title of the browser tab
Name of the browser
Version of the browser
Domain of the browser
URL of the browser tab
Title of the browser tab
Thick app identifier (e.g. THICK_APP_SLACK, THICK_APP_OUTLOOK)
Official domain of the application
Email of the user in the application context
Path of the file involved
Name of the file involved
Hash of the file involved
Unix timestamp in milliseconds when the upload started
Unix timestamp in milliseconds when the upload ended
Name of the application
AI agent client identifier (e.g. "claude_code", "cursor", "cowork")
Version of the AI agent client
Email of the user driving the AI agent session
Phase of the agent interaction this event represents
AI agent session identifier
Tool invoked (TOOL_REQUEST / TOOL_RESPONSE only)
MCP server that served the tool, when applicable
JSON-encoded tool input
JSON-encoded tool response (truncated at 128KB)
User prompt text (PROMPT only)
Model response text (MODEL_RESPONSE only)
Shell command executed (SHELL only)
Permission decision for the action
Position within the agent activity chain (0 = prompt, 1+ = tools)
Unique identifier for a specific tool invocation
Model used for the request (OTel only, e.g. "claude-opus-4-7")
Cost in USD for this event (OTel only)
Input tokens consumed (OTel only)
Output tokens produced (OTel only)
Tool or API call duration in milliseconds
Error message when the agent call failed (api_error only)
Thick app identifier (e.g. THICK_APP_SLACK, THICK_APP_OUTLOOK)
Official domain of the application
Email of the user in the application context
Path of the file involved
Name of the file involved
Hash of the file involved
Unix timestamp in milliseconds when the upload started
Unix timestamp in milliseconds when the upload ended
Type of print operation
Print destination
Number of copies
Name of the printer
Printer manufacturer
Printer model
Combined printer make and model
Application that initiated the print (e.g. "Adobe Acrobat")
Unix timestamp in milliseconds when the print job was queued
Name of the git repository
Process that invoked git (e.g. the IDE or shell)
Destination repository URL
Name of the remote
URL of the remote
Name of the transferred file
Hash of the transferred file
Size of the file in bytes
Inode identifier of the file
Source path of the file
Destination path on the removable media
Unix timestamp in milliseconds when the transfer started
Unix timestamp in milliseconds when the transfer ended
Mount path of the removable media
Volume label of the removable media
Vendor ID of the device
Vendor name of the device
Serial number of the device
Type of removable media (e.g. REMOVABLE_MEDIA_TYPE_USB)
ID of the originating app
Name of the originating app
Whether this is a client sync event
Source IP address
Level of the session
Key of the session
Salesforce user ID
asset IDs associated with the event
Actions that can be taken on the event
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Event does not exist
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /exfiltration/v1/events/{eventId} HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"policyUUIDs": [
"123e4567-e89b-12d3-a456-426614174000"
],
"policyNames": [
"text"
],
"assets": [
{
"id": "text",
"name": "text",
"path": "text",
"sizeBytes": 1,
"mimetype": "text",
"owner": {
"id": "text",
"email": "name@gmail.com",
"comment": "text",
"metadata": {
"gdrive": {
"userBelongsToGroups": [
"text"
],
"isAdmin": true,
"isSuspended": true,
"createdAt": 1
},
"salesforce": {},
"endpointAgent": {
"deviceID": "text",
"machineName": "text"
}
}
},
"comment": "text",
"ddrViolationIDs": [
"123e4567-e89b-12d3-a456-426614174000"
],
"metadata": {
"gdrive": {
"fileID": "text",
"fileName": "text",
"fileSize": "text",
"fileLink": "text",
"permissionSetting": "text",
"sharingExternalUsers": [
"text"
],
"sharingInternalUsers": [
"text"
],
"canViewersDownload": true,
"fileOwner": "text",
"isInTrash": true,
"createdAt": 1,
"updatedAt": 1,
"drive": "text",
"labels": [
"text"
],
"filePermissionType": "text"
},
"salesforce": {
"resourceType": "text",
"fileResourceMetadata": {
"fileAction": "text",
"sourceIP": "text",
"sessionLevel": "text"
},
"reportResourceMetadata": {
"description": "text",
"displayEntityFields": [
"text"
],
"dashboardName": "text",
"scope": "text",
"operation": "text",
"recordCount": 1,
"queriedEntities": [
"text"
],
"groupedColumnHeaders": [
"text"
],
"columnCount": 1,
"processedRowCount": 1,
"sourceIP": "text",
"eventSource": "text",
"sessionLevel": "text"
},
"bulkApiResourceMetadata": {
"query": "text",
"eventIdentifier": "text",
"sourceIP": "text",
"sessionKey": "text",
"sessionLevel": "text"
}
},
"endpointAgent": {
"medium": "EXFIL_MEDIUM_USB",
"mediumName": "text",
"user": "text"
}
}
}
],
"actor": {
"id": "text",
"email": "name@gmail.com",
"comment": "text",
"metadata": {
"gdrive": {
"userBelongsToGroups": [
"text"
],
"isAdmin": true,
"isSuspended": true,
"createdAt": 1
},
"salesforce": {},
"endpointAgent": {
"deviceID": "text",
"machineName": "text"
}
}
},
"events": [
{
"type": "DOWNLOAD",
"timestamp": 1,
"metadata": {
"endpointAgent": {
"endpointBrowserUploadMetadata": {
"browserName": "text",
"browserVersion": "text",
"domain": "text",
"browserTabURL": "text",
"browserTabTitle": "text",
"uploadStartTime": 1,
"uploadEndTime": 1,
"fileName": "text",
"originMetadata": [
{
"timestamp": 1,
"browserDownloadMetadata": {
"browserName": "text",
"browserVersion": "text",
"domain": "text",
"browserTabURL": "text",
"browserTabTitle": "text",
"downloadStartTime": 1,
"downloadEndTime": 1
},
"clipboardCopyMetadata": {
"contentType": "CCT_TEXT",
"browserMetadata": {
"browserName": "text",
"browserVersion": "text",
"domain": "text",
"browserTabURL": "text",
"browserTabTitle": "text"
}
}
}
]
},
"endpointCloudSyncMetadata": {
"app": "text",
"accountType": "text",
"accountName": "text",
"email": "text",
"destinationFilePath": "text",
"uploadStartTime": 1,
"uploadEndTime": 1,
"fileName": "text"
},
"endpointClipboardMetadata": {
"contentType": "text",
"appType": "text",
"originMetadata": [
{
"timestamp": 1,
"browserDownloadMetadata": {
"browserName": "text",
"browserVersion": "text",
"domain": "text",
"browserTabURL": "text",
"browserTabTitle": "text",
"downloadStartTime": 1,
"downloadEndTime": 1
},
"clipboardCopyMetadata": {
"contentType": "CCT_TEXT",
"browserMetadata": {
"browserName": "text",
"browserVersion": "text",
"domain": "text",
"browserTabURL": "text",
"browserTabTitle": "text"
}
}
}
],
"destinationMetadata": {
"browserMetadata": {
"browserName": "text",
"browserVersion": "text",
"domain": "text",
"browserTabURL": "text",
"browserTabTitle": "text"
},
"thickAppMetadata": {
"thickApp": "text",
"officialDomain": "text",
"userEmail": "text",
"appMetadata": {
"ANY_ADDITIONAL_PROPERTY": "text"
},
"filePath": "text",
"fileName": "text",
"fileHash": "text",
"uploadStartTime": 1,
"uploadEndTime": 1
},
"genericAppMetadata": {
"appName": "text"
}
}
},
"aiAgentMetadata": {
"clientType": "text",
"clientVersion": "text",
"userEmail": "text",
"triggerPoint": "PROMPT",
"sessionId": "text",
"toolName": "text",
"serverName": "text",
"toolInput": "text",
"toolResponse": "text",
"promptText": "text",
"responseText": "text",
"shellCommand": "text",
"decision": "allow",
"sequenceOrder": 1,
"toolUseId": "text",
"model": "text",
"costUsd": 1,
"inputTokens": 1,
"outputTokens": 1,
"durationMs": 1,
"errorMessage": "text"
},
"thickAppMetadata": {
"thickApp": "text",
"officialDomain": "text",
"userEmail": "text",
"appMetadata": {
"ANY_ADDITIONAL_PROPERTY": "text"
},
"filePath": "text",
"fileName": "text",
"fileHash": "text",
"uploadStartTime": 1,
"uploadEndTime": 1
},
"printMetadata": {
"printType": "text",
"printDestination": "text",
"copies": 1,
"printerName": "text",
"printerMake": "text",
"printerModel": "text",
"printerMakeAndModel": "text",
"applicationName": "text",
"queuedTime": 1
},
"gitPushMetadata": {
"repoName": "text",
"parentProcessName": "text",
"destinationURL": "text",
"remotes": [
{
"name": "text",
"url": "text"
}
]
},
"removableMediaTransferMetadata": {
"fileName": "text",
"fileHash": "text",
"fileSize": 1,
"fileInodeID": "text",
"sourcePath": "text",
"destinationPath": "text",
"startTime": 1,
"endTime": 1,
"mountPath": "text",
"volumeLabel": "text",
"vendorID": "text",
"vendorName": "text",
"serialNumber": "text",
"mediaType": "text"
}
},
"gdrive": {
"originatingAppId": "text",
"originatingAppName": "text",
"isClientSyncEvent": true
},
"salesforce": {
"sourceIP": "text",
"sessionLevel": "text",
"sessionKey": "text",
"sfUserId": "text"
}
},
"assetIDs": [
"text"
]
}
],
"possibleActions": [
"text"
]
}Fetch the activity feed for a specific exfiltration event
The UUID of the exfiltration event
Number of activity items to fetch in one page
50Unix timestamp in seconds, filters activity created > the value
Unix timestamp in seconds, filters activity created < the value
Whether to sort results in descending order (default false)
falseCursor for getting the next page of results
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
Unique identifier for the activity log entry
Human-readable message describing the activity
Unix timestamp in seconds when the activity occurred
Next page cursor, omitted if end of results reached
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Event does not exist
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /exfiltration/v1/events/{eventId}/activity HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"activities": [
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"message": "text",
"timestamp": 1,
"type": "CREATION",
"data": {
"action": "ACKNOWLEDGE",
"userUUID": "123e4567-e89b-12d3-a456-426614174000",
"userName": "text",
"userEmail": "text",
"receiverEmail": "text",
"actionLogData": {
"applyLabelsActionLogData": {
"activityType": "LABELS_SUCCESSFULLY_APPLIED",
"labels": [
"text"
],
"labelUpdatesOnResource": {
"ANY_ADDITIONAL_PROPERTY": "text"
},
"failureReason": "text"
},
"setExpirationActionLogData": {
"expirationTime": 1
},
"revokeAccessActionLogData": {
"revokedEmails": [
"text"
],
"unRevokedEmails": [
"text"
]
},
"notifyEmailActionLogData": {
"receiverEmail": "text"
},
"genericActionLogData": {
"additionalContext": "text"
},
"blockActionActionLogData": {
"isBlocked": true,
"blockReason": "text",
"skippedReason": "text"
}
}
}
}
],
"nextPageToken": "text"
}Fetch the activity history for a specific asset
The ID of the asset to fetch activities for
Unix timestamp in seconds, filters activities created ≥ the value
Unix timestamp in seconds, filters activities created < the value
Cursor for getting the next page of results
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
Type of the activity
Email of the user who performed the activity
Unix timestamp in seconds indicating when the activity occurred
Names of assets involved in the activity
Source of the download
Name of the downloaded file
Domain where the upload occurred
Name of the uploaded file
Cloud application used for synchronization
Name of the synchronized file
Domain related to the clipboard activity
Thick app identifier (e.g. THICK_APP_SLACK, THICK_APP_OUTLOOK)
Name of the generic application
Type of app involved in the clipboard event (e.g. CAT_BROWSER, CAT_THICK_APP, CAT_GENERIC_APP)
Next page cursor, omitted if end of results reached
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /exfiltration/v1/asset/activity?assetID=text&rangeStart=1&rangeEnd=1 HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"activities": [
{
"type": "DOWNLOAD",
"userEmail": "name@gmail.com",
"eventTime": 1,
"assetNames": [
"text"
],
"metadata": {
"downloadEventMetadata": {
"source": "text",
"fileName": "text"
},
"browserUploadMetadata": {
"domain": "text",
"fileName": "text"
},
"cloudSyncMetadata": {
"cloudApp": "text",
"fileName": "text"
},
"clipboardMetadata": {
"browserMetadata": {
"domain": "text"
},
"thickAppMetadata": {
"thickApp": "text"
},
"genericAppMetadata": {
"appName": "text"
},
"appType": "text"
}
}
}
],
"nextPageToken": "text"
}Fetch the activity history for a specific actor
The Nightfall ID of the actor to fetch activities for
Unix timestamp in seconds, filters activities created ≥ the value
Unix timestamp in seconds, filters activities created < the value
Cursor for getting the next page of results
Successful response
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
Type of the activity
Email of the user who performed the activity
Unix timestamp in seconds indicating when the activity occurred
Names of assets involved in the activity
Source of the download
Name of the downloaded file
Domain where the upload occurred
Name of the uploaded file
Cloud application used for synchronization
Name of the synchronized file
Domain related to the clipboard activity
Thick app identifier (e.g. THICK_APP_SLACK, THICK_APP_OUTLOOK)
Name of the generic application
Type of app involved in the clipboard event (e.g. CAT_BROWSER, CAT_THICK_APP, CAT_GENERIC_APP)
Next page cursor, omitted if end of results reached
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
GET /exfiltration/v1/actor/activity?actorID=text&rangeStart=1&rangeEnd=1 HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"activities": [
{
"type": "DOWNLOAD",
"userEmail": "name@gmail.com",
"eventTime": 1,
"assetNames": [
"text"
],
"metadata": {
"downloadEventMetadata": {
"source": "text",
"fileName": "text"
},
"browserUploadMetadata": {
"domain": "text",
"fileName": "text"
},
"cloudSyncMetadata": {
"cloudApp": "text",
"fileName": "text"
},
"clipboardMetadata": {
"browserMetadata": {
"domain": "text"
},
"thickAppMetadata": {
"thickApp": "text"
},
"genericAppMetadata": {
"appName": "text"
},
"appType": "text"
}
}
}
],
"nextPageToken": "text"
}Update a policy user scope, define inclusion/exclusion rule for users using user emails. Only supports gDrive policies, separates internal or external users based on google domains registered in Nightfall.
The UUID of the policy to update
user emails to be added in inclusion setting, supports both internal & external users
user emails to be added in exclusion setting, supports both internal & external users
user emails to be removed in inclusion setting, supports both internal & external users
user emails to be removed in exclusion setting, supports both internal & external users
Successful response (processed immediately)
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
a list of all included user identifiers (emails or id's) in the policy
a list of all excluded user identifiers (emails or id's) in the policy
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Operation prohibited on the policy
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Policy not found
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
POST /policy/v1/{policyID}/scope/users HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 136
{
"add": {
"include": [
"name@gmail.com"
],
"exclude": [
"name@gmail.com"
]
},
"delete": {
"include": [
"name@gmail.com"
],
"exclude": [
"name@gmail.com"
]
}
}{
"includedUsers": [
"text"
],
"excludedUsers": [
"text"
]
}Update a policy domain scope, define inclusion/exclusion rule for domains. Only supports gDrive policies.
The UUID of the policy to update
domains to be added in inclusion setting
domains to be added in exclusion setting
domains to be removed in inclusion setting
domains to be removed in exclusion setting
Successful response (processed immediately)
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
a list of all included domains in the policy
a list of all excluded domains in the policy
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Operation prohibited on the policy
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Policy not found
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
POST /policy/v1/{policyID}/scope/domains HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 96
{
"add": {
"include": [
"text"
],
"exclude": [
"text"
]
},
"delete": {
"include": [
"text"
],
"exclude": [
"text"
]
}
}{
"includedDomains": [
"text"
],
"excludedDomains": [
"text"
]
}Update trigger-scoped users for a posture management policy. Modifies users stored in the trigger scope. Only supports posture management policies of gDrive.
The UUID of the policy to update
user emails to be added in inclusion setting
user emails to be added in exclusion setting
user emails to be removed from inclusion setting
user emails to be removed from exclusion setting
Successful response (processed immediately)
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
a list of all included user identifiers (emails or IDs) in the policy trigger scope
a list of all excluded user identifiers (emails or IDs) in the policy trigger scope
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Operation prohibited on the policy
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Policy not found
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
POST /policy/v1/{policyID}/trigger/users HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 136
{
"add": {
"include": [
"name@gmail.com"
],
"exclude": [
"name@gmail.com"
]
},
"delete": {
"include": [
"name@gmail.com"
],
"exclude": [
"name@gmail.com"
]
}
}{
"includedUsers": [
"text"
],
"excludedUsers": [
"text"
]
}Update trigger-scoped domains for a posture management policy. Modifies domains stored in trigger scope. Only supports posture management policies of gDrive.
The UUID of the policy to update
domains to be added in inclusion setting
domains to be added in exclusion setting
domains to be removed from inclusion setting
domains to be removed from exclusion setting
Successful response (processed immediately)
How many remaining requests you can make within the next second before being throttled
How many remaining requests you can make within the next quota period
When the current quota period expires
a list of all included domains in the policy trigger scope
a list of all excluded domains in the policy trigger scope
Invalid request parameters
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Authentication failure
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Operation prohibited on the policy
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Policy not found
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Rate Limit Exceeded or Daily Quota Exceeded
Seconds after which to retry the request
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
Internal Nightfall Error
A status code to uniquely describe this error.
A message associated with the status code.
Additional details to explain what may have occurred. Omitted if empty.
POST /policy/v1/{policyID}/trigger/domains HTTP/1.1
Host: api.nightfall.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 96
{
"add": {
"include": [
"text"
],
"exclude": [
"text"
]
},
"delete": {
"include": [
"text"
],
"exclude": [
"text"
]
}
}{
"includedDomains": [
"text"
],
"excludedDomains": [
"text"
]
}