# nodes

node_type: n8n-nodes-fluentc.fluentC
package_name: n8n-nodes-fluentc
display_name: FluentC
description: Translate content, detect languages, and retrieve supported languages using FluentC AI
category: Community
development_style: declarative
version: 1
credentials_required: []
outputs:
  [
  "main"
  ]

updated_at: 2026-07-14 14:40:34
author_name: fluentc
author_github_url: https://github.com/FluentC/
npm_package_name: n8n-nodes-fluentc
npm_version: 2.0.2
community_fetched_at: 2026-07-14T14:40:34.468Z
ai_summary_generated_at: 2026-06-26 10:29:17
properties_schema:
  [
    {
      "name": "resource",
      "type": "options",
      "default": "translation",
      "options": [
        {
          "name": "Translation",
          "value": "translation"
        },
        {
          "name": "Language Detection",
          "value": "languageDetection"
        },
        {
          "name": "Language",
          "value": "language"
        }
      ],
      "displayName": "Resource",
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "translate",
      "options": [
        {
          "name": "Translate",
          "value": "translate",
          "action": "Translate content",
          "description": "Translate text, HTML, or JSON content"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "translation"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "detect",
      "options": [
        {
          "name": "Detect",
          "value": "detect",
          "action": "Detect language",
          "description": "Detect the language of text or HTML content"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "languageDetection"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getMany",
      "options": [
        {
          "name": "Get Many",
          "value": "getMany",
          "action": "Get many languages",
          "description": "Get supported and source languages"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "language"
          ]
        }
      },
      "noDataExpression": true
    }
  ]

operations:
  [
    {
      "name": "Translate",
      "value": "translate",
      "action": "Translate content",
      "description": "Translate text, HTML, or JSON content",
      "resource": "translation"
    },
    {
      "name": "Detect",
      "value": "detect",
      "action": "Detect language",
      "description": "Detect the language of text or HTML content",
      "resource": "languageDetection"
    },
    {
      "name": "Get Many",
      "value": "getMany",
      "action": "Get many languages",
      "description": "Get supported and source languages",
      "resource": "language"
    }
  ]

npm_readme:
  # FluentC N8N Plugin

  This N8N community plugin provides integration with the FluentC AI Translation API, enabling you to translate text and HTML content and detect languages within your N8N workflows.

  ## Features

  - **Translation**: Support for both real-time and batch translation modes
  - **Language Detection**: Detect the language of input content
  - **Language Retrieval**: Fetch lists of supported and source languages
  - **Dynamic Language Selection**: Dropdown menus populated with your API key's enabled languages
  - **Format Support**: Handle text, HTML, and JSON content
  - **Automatic Polling**: Batch jobs are automatically polled until completion
  - **Comprehensive Output**: Returns all metadata including token counts, detected languages, and model information
  - **Error Handling**: Graceful error handling with continue-on-fail support
  - **Language Management**: Direct link to manage enabled languages on your account

  ## Installation

  The installation method depends on your n8n setup. Choose the appropriate method below:

  ### Method 1: n8n GUI Installation (Recommended for self-hosted n8n)

  This is the easiest method for self-hosted n8n instances:

  1. **Open n8n Settings**: In your n8n instance, go to **Settings** > **Community Nodes**
  2. **Install Node**: Click **Install**
  3. **Enter Package Name**: Enter `n8n-nodes-fluentc` in the "Enter npm package name" field
  4. **Accept Risk**: Check "I understand the risks of installing unverified code from a public source"
  5. **Install**: Click **Install**
  6. **Restart**: The nodes will be available immediately after installation

  ### Method 2: Verified Community Nodes (for n8n Cloud and recent versions)

  If this package gets verified by n8n (future goal):

  1. **Open Nodes Panel**: Go to the Canvas and open the nodes panel (click '+' or press Tab)
  2. **Search**: Search for "FluentC"
  3. **Install from Community**: Look for the "More from the community" section
  4. **Install**: Click on the FluentC node and select **Install**

  ### Method 3: Manual Installation (for Docker/advanced setups)

  For Docker containers, queue mode, or when GUI installation isn't available:

  #### For Docker Containers:

  1. **Access Docker Shell**:
     ```bash
     docker exec -it [your-n8n-container-name] sh
     ```

  2. **Create nodes directory** (if it doesn't exist):
     ```bash
     mkdir -p ~/.n8n/nodes
     cd ~/.n8n/nodes
     ```

  3. **Install the package**:
     ```bash
     npm install n8n-nodes-fluentc
     ```

  4. **Restart n8n container**

  #### For npm-based installations:

  1. **Navigate to n8n nodes directory**:
     ```bash
     cd ~/.n8n/nodes
     ```
     (Create the directory if it doesn't exist: `mkdir -p ~/.n8n/nodes`)

  2. **Install the package**:
     ```bash
     npm install n8n-nodes-fluentc
     ```

  3. **Restart n8n**

  ### Method 4: Custom Docker Build

  For permanent installation in a custom Docker image:

  ```dockerfile
  FROM n8nio/n8n:latest
  RUN cd ~/.n8n/ && mkdir -p nodes && cd nodes && npm install n8n-nodes-fluentc
  ```

  ## Verification

  After installation, verify the node is available:

  1. Create a new workflow
  2. Click the '+' button to add a node
  3. Search for "FluentC" in the node search
  4. You should see the **FluentC** node (with package icon)

  ## Setup

  ### 1. Create FluentC API Credentials

  1. In N8N, go to **Credentials** > **New**
  2. Search for "FluentC API" and select it
  3. Enter your FluentC API key (obtained from the FluentC sales website)
  4. Test and save the credential

  ### 2. Using the Node

  The FluentC node uses a **Resource** and **Operation** pattern. Select the resource for the task you want to perform, then choose the operation.

  #### Translation > Translate

  Translate text, HTML, or JSON content with support for both real-time and batch modes.

  **Parameters:**
  - **Mode**: Choose between "Real-Time" (synchronous) or "Batch" (asynchronous)
  - **Input**: Text, HTML, or JSON content to translate (max 100,000 bytes)
  - **Input Format**: Select "Text", "HTML", or "JSON"
  - **Target Language**: Dropdown populated with your enabled target languages
  - **Source Language**: Dropdown with your enabled source languages (optional, includes "Auto-Detect")
  - **Max Polling Attempts**: (Batch mode only) Maximum polling attempts for batch jobs (default: 60)

  **Language Management:**
  The language dropdowns are dynamically populated based on your API key's enabled languages. If you need additional languages, you'll see a link to visit www.fluentc.io to manage your language access.

  **Output:**
  The node returns all available data including:
  - `translation`: The translated content
  - `token_count`: Number of tokens used
  - `source_language_detected`: Detected source language
  - `model_used`: AI model used for translation
  - `metadata`: Additional metadata
  - `mode`: Translation mode used
  - `input_format`: Input format processed
  - `target_language`: Target language

  #### Language Detection > Detect

  Detect the language of input content.

  **Parameters:**
  - **Input**: Text or HTML content to analyze
  - **Input Format**: Select "Text" or "HTML"

  **Output:**
  - `detected_language`: Two-letter language code of detected language
  - `confidence`: Confidence score (0-1) for the detection
  - `input_format`: Input format processed
  - `input_length`: Length of analyzed content

  #### Language > Get Many

  Fetch the lists of supported and source languages from your FluentC account.

  **Parameters:**
  This operation has no additional parameters. It only requires a configured FluentC API credential.

  **Output:**
  - `supported_languages`: An array of objects, each with `code` and `name` of a language available for translation as a target.
  - `source_languages`: An array of objects, each with `code` and `name` of a language available as a source for translation.

  ## Usage Examples

  ### Basic Translation Workflow

  1. Add a **FluentC** node to your workflow
  2. Select Resource: **Translation**, Operation: **Translate**
  3. Configure it with:
     - Mode: "Real-Time"
     - Input: "Hello, how are you today?"
     - Input Format: "Text"
     - Target Language: Select "Spanish (es)" from dropdown
  4. The output will include the Spanish translation and metadata

  ### Batch Translation for Large Content

  1. Use the **FluentC** node with Resource: **Translation**, Operation: **Translate**
  2. Configure with:
     - Mode: "Batch"
     - Input: Your large HTML or text content
     - Target Language: Your desired language code
  3. The node will automatically poll until the translation is complete

  ### Language Detection Before Translation

  1. Add a **FluentC** node with Resource: **Language Detection**, Operation: **Detect**
  2. Connect it to another **FluentC** node with Resource: **Translation**, Operation: **Translate**
  3. Use the detected language as the source language parameter

  ### Retrieving Language Lists

  1. Add a **FluentC** node with Resource: **Language**, Operation: **Get Many**
  2. Execute the node
  3. The output will contain two arrays: `supported_languages` and `source_languages`, which you can use in other parts of your workflow

  ## Migration from v1.x

  Version 2.0 consolidates the three separate nodes from v1.x into a single **FluentC** node:

  | v1.x Node | v2.0 Resource | v2.0 Operation |
  |---|---|---|
  | FluentC Translate | Translation | Translate |
  | FluentC Check Language | Language Detection | Detect |
  | FluentC Languages | Language | Get Many |

  Existing workflows using the old nodes must be updated manually. Parameter names within each operation remain the same, so expressions referencing fields like `input`, `targetLanguage`, or `mode` should continue to work after migration.

  ## Troubleshooting

  ### Node Not Appearing

  If the node doesn't appear after installation:

  1. **Check Installation Method**: Ensure you used the correct method for your setup
  2. **Restart n8n**: Always restart n8n after manual installation
  3. **Check Directory**: For manual installs, verify the package is in `~/.n8n/nodes/`
  4. **Check Permissions**: Ensure n8n has read permissions for the nodes directory
  5. **Check Logs**: Look at n8n logs for any error messages during startup

  ### Permission Issues

  For Docker installations, you might need to ensure proper permissions:

  ```bash
  # Inside the container
  chown -R node:node ~/.n8n/nodes
  ```

  ### Queue Mode

  If you're running n8n in queue mode, you **must** use manual installation (Method 3).

  ## Error Handling

  The plugin includes comprehensive error handling:

  - **Content Size Validation**: Prevents requests exceeding 100,000 bytes
  - **Batch Timeout Protection**: Limits polling attempts to prevent infinite loops
  - **API Error Handling**: Gracefully handles API errors and rate limits
  - **Continue on Fail**: Option to continue workflow execution even if translation fails

  ## API Rate Limits

  The plugin respects FluentC API rate limits and uses the recommended polling intervals returned by the batch API to avoid overwhelming the service.

  ## Development & Publishing

  This package follows n8n community node standards:

  - ✅ Package name starts with `n8n-nodes-`
  - ✅ Includes `n8n-community-node-package` keyword
  - ✅ No runtime dependencies (only devDependencies)
  - ✅ Proper n8n configuration in package.json
  - ✅ Built TypeScript with proper exports
  - ✅ Single action node with Resource/Operation pattern

  ## Support

  For issues related to this N8N plugin, please check:

  1. **FluentC API Documentation**: https://fluentc.ai/docs
  2. **N8N Community**: https://community.n8n.io
  3. **Plugin Repository**: https://github.com/FluentC/n8n-nodes-fluentc
  4. **n8n Community Nodes Documentation**: https://docs.n8n.io/integrations/community-nodes/

  ## License

  MIT License - see LICENSE file for details.

  ---

  **Note**: You need a valid FluentC API key to use this plugin. API keys are obtained through the FluentC sales website.

ai_documentation_summary:
  {"purpose":"Integrates FluentC AI Translation API into n8n workflows to translate content, detect languages, and retrieve available language lists. It supports text, HTML, and JSON translation with both real-time and batch processing.","capabilities":["Translate text, HTML, or JSON content","Run translations in real-time or batch mode","Automatically poll batch translation jobs until completion","Detect the language of input text or HTML content","Fetch supported target languages and source languages","Use dynamic language dropdowns based on the API key's enabled languages","Return detailed metadata such as token counts, detected language, model used, and processing mode","Handle errors with continue-on-fail support"],"authentication":"FluentC API key required via n8n credentials","commonUseCases":["Translating multilingual content in automation workflows","Detecting the language of user-submitted text or HTML","Retrieving available translation languages before running a translation"],"limitations":["Translation input is limited to 100,000 bytes","Language selections depend on the languages enabled for the API key"],"relatedNodes":[]}


node_type: @g-digital/n8n-nodes-ead-enterprise-suite.eadEnterpriseSuite
package_name: @g-digital/n8n-nodes-ead-enterprise-suite
display_name: EAD Enterprise Suite
description: MCP server for EAD Enterprise Suite - signatures, evidence, notifications, dossiers via AI agents.
category: Community
development_style: declarative
version: 1
credentials_required: []
outputs:
  [
  "main"
  ]

updated_at: 2026-07-14 14:40:34
author_name: g-digital-bot
author_github_url: https://github.com/g-digital-by-Garrigues/EAD_Enterprise_Suite_MCP.git
npm_package_name: @g-digital/n8n-nodes-ead-enterprise-suite
npm_version: 1.4.2
community_fetched_at: 2026-07-14T14:40:34.470Z
ai_summary_generated_at: 2026-06-26 10:29:17
properties_schema:
  [
    {
      "name": "resource",
      "type": "options",
      "default": "caseFile",
      "options": [
        {
          "name": "Case File",
          "value": "caseFile"
        },
        {
          "name": "Evidence",
          "value": "evidence"
        },
        {
          "name": "Dossier Evidence",
          "value": "dossierEvidence"
        },
        {
          "name": "Dossier",
          "value": "dossier"
        },
        {
          "name": "Notification",
          "value": "notification"
        },
        {
          "name": "Signature",
          "value": "signature"
        },
        {
          "name": "Session",
          "value": "session"
        },
        {
          "name": "Use Case",
          "value": "useCase"
        }
      ],
      "displayName": "Resource",
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "case_file_create",
      "options": [
        {
          "name": "Create Case File",
          "value": "case_file_create",
          "action": "Create Case File",
          "description": "Creates a new case file — the top-level container for all related operations (evidence, notifications, signatures, dossiers). Call this first before any other operation. Generate a UUID v4 for `id`. Returns caseFileId needed for all subsequent calls."
        },
        {
          "name": "List Case File",
          "value": "case_file_list",
          "action": "List Case File",
          "description": "Lists all case files in your EAD Enterprise Suite account. Pass userId (from session_login or session_info) to scope results to your account. Returns paginated list with IDs, names, and status."
        },
        {
          "name": "Get Case File",
          "value": "case_file_get",
          "action": "Get Case File",
          "description": "Retrieves details of a specific case file. Requires: caseFileId. Use to verify a case file exists before creating evidence groups, dossiers, or signature requests."
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "caseFile"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "evidence_create",
      "options": [
        {
          "name": "Create Evidence",
          "value": "evidence_create",
          "action": "Create Evidence",
          "description": "Registers a NEW evidence record inside an evidence group. Requires: evidence_group_create → evidenceGroupId, case_file_create → caseFileId. Generate a UUID v4 for `id`. Compute the SHA-256 hex hash of the file BEFORE calling. Normal INTERNAL flow: call evidence_create with custodyType INTERNAL and NO fileUrl; the API returns uploadFileUrl, a presigned S3 URL. You MUST PUT the exact file bytes to uploadFileUrl, then verify with evidence_get/evidence_list, and ONLY THEN call evidence_seal. Do not seal an evidence group until every INTERNAL evidence file has been uploaded. Convenience flow: if you pass `fileUrl` (public HTTPS, no redirects, under 1 GiB), this tool downloads that URL and PUTs the bytes to uploadFileUrl for you. EXTERNAL flow: use custodyType EXTERNAL only when you intentionally register hash-only evidence; still generate a fresh UUID for each evidence. If an INTERNAL evidence creation/upload failed and you want to retry as EXTERNAL, create a NEW evidence id; do not reuse an id whose outcome is unknown. WARNING: the API sometimes returns {code:'EvidenceCreateError'} even when the evidence was successfully persisted — always verify with evidence_list before retrying."
        },
        {
          "name": "List Evidence",
          "value": "evidence_list",
          "action": "List Evidence",
          "description": "Lists all evidence records in a specific evidence group. Requires: caseFileId and evidenceGroupId. Returns paginated list with IDs, titles, status, and timestamps."
        },
        {
          "name": "Seal Evidence",
          "value": "evidence_seal",
          "action": "Seal Evidence",
          "description": "Seal and certify an evidence group. Closes the group to new additions and triggers async timestamping. Returns immediately — the group transitions OPEN → CLOSING → CLOSED. Poll evidence_group_list until status is CLOSED before linking to a dossier."
        },
        {
          "name": "Get Evidence",
          "value": "evidence_get",
          "action": "Get Evidence",
          "description": "Retrieves a specific evidence record. Requires: evidence_create → evidenceId, evidence_group_create → evidenceGroupId, case_file_create → caseFileId. Returns status (COMPLETED|IN_PROCESS|ERROR), hash, and tspTimestamp when certified."
        },
        {
          "name": "Create Evidence Group",
          "value": "evidence_group_create",
          "action": "Create Evidence Group",
          "description": "Creates an evidence group inside a case file. Requires: case_file_create → caseFileId. Generate a UUID v4 for `id`. Set evidenceType to FILE, PHOTO, VIDEO, or WEB_PLUGIN. Returns evidenceGroupId. One group can contain multiple evidence records."
        },
        {
          "name": "List Evidence Group",
          "value": "evidence_group_list",
          "action": "List Evidence Group",
          "description": "Lists all evidence groups in a case file with their current status (OPEN, CLOSING, CLOSED). Use to find an existing group or check which groups are ready for sealing. Requires: caseFileId."
        },
        {
          "name": "Initiate Large Evidence Upload",
          "value": "large_evidence_upload_initiate",
          "action": "Initiate Large Evidence Upload",
          "description": "Performs the large_evidence_upload_initiate operation against the GoCertius API. Review the API documentation for full field details."
        },
        {
          "name": "Complete Large Evidence Upload",
          "value": "large_evidence_upload_complete",
          "action": "Complete Large Evidence Upload",
          "description": "Finalize a multipart evidence upload and register the evidence in the group. Returns immediately — the evidence transitions asynchronously to COMPLETED. Poll evidence_list until status is COMPLETED before sealing the group."
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "evidence"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "dossier_evidence_link",
      "options": [
        {
          "name": "Link Dossier Evidence",
          "value": "dossier_evidence_link",
          "action": "Link Dossier Evidence",
          "description": "Links evidence items from a sealed group to a dossier. Requires: dossier_create → dossierId, evidence_seal (CLOSED), case_file_create → caseFileId. Pass the ids array of evidence UUIDs. Can be called multiple times for evidence from different case files."
        },
        {
          "name": "Dossier Evidence List To Link",
          "value": "dossier_evidence_list_to_link",
          "action": "Dossier Evidence List To Link",
          "description": "Lists evidence items available to be linked to a dossier (CLOSED groups not yet linked). Requires: caseFileId and dossierId."
        },
        {
          "name": "List Dossier Evidence",
          "value": "dossier_evidence_list",
          "action": "List Dossier Evidence",
          "description": "Lists all evidence items linked to a dossier. Requires: caseFileId and dossierId."
        },
        {
          "name": "Get Dossier Evidence",
          "value": "dossier_evidence_get",
          "action": "Get Dossier Evidence",
          "description": "Retrieves details of a specific evidence item linked to a dossier. Requires: caseFileId, dossierId, evidenceId."
        },
        {
          "name": "Delete Dossier Evidence",
          "value": "dossier_evidence_delete",
          "action": "Delete Dossier Evidence",
          "description": "Removes an evidence item from a dossier. Only available while dossier is in DRAFT status. Requires: caseFileId, dossierId, evidenceId."
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "dossierEvidence"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "dossier_create",
      "options": [
        {
          "name": "Create Dossier",
          "value": "dossier_create",
          "action": "Create Dossier",
          "description": "Creates a dossier to aggregate certified evidence groups into a single tamper-evident PDF. Requires: case_file_create → caseFileId. Evidence groups must be in CLOSED status before linking. Generate a UUID v4 string for `id`. Returns dossierId. After creation, link evidence with dossier_evidence_link, then certify with dossier_certify."
        },
        {
          "name": "Update Dossier",
          "value": "dossier_update",
          "action": "Update Dossier",
          "description": "Updates the metadata of an existing dossier. Requires: dossier_create → dossierId, caseFileId. Only available while dossier is in DRAFT status."
        },
        {
          "name": "Certify Dossier",
          "value": "dossier_certify",
          "action": "Certify Dossier",
          "description": "Certifies a dossier, generating a tamper-evident PDF and locking all linked evidence. Requires: dossier_create → dossierId, dossier_evidence_link (evidence linked), case_file_create → caseFileId. ASYNC: transitions DRAFT → CERTIFYING → CERTIFIED. Poll dossier_list until dossierId status === CERTIFIED."
        },
        {
          "name": "List Dossier",
          "value": "dossier_list",
          "action": "List Dossier",
          "description": "Lists all dossiers in a case file. Requires: caseFileId. Returns paginated list with IDs, names, status, and creation dates. Use to monitor certification progress — poll until status: CERTIFIED."
        },
        {
          "name": "Get Dossier",
          "value": "dossier_get",
          "action": "Get Dossier",
          "description": "Retrieves full details of a specific dossier including status, linked evidence, and download URLs. Requires: caseFileId and dossierId."
        },
        {
          "name": "List Dossier Template",
          "value": "dossier_template_list",
          "action": "List Dossier Template",
          "description": "Lists available dossier templates. No prerequisites. Returns template IDs and their translations per language. Use the returned id as dossierTemplateId in dossier_create."
        },
        {
          "name": "Preview Dossier",
          "value": "dossier_preview",
          "action": "Preview Dossier",
          "description": "Returns an HTML preview URL of a dossier before certification. Requires: caseFileId and dossierId."
        },
        {
          "name": "Dossier Document Url",
          "value": "dossier_document_url",
          "action": "Dossier Document Url",
          "description": "Returns the download URL for the certified dossier PDF. Requires: dossier_certify (CERTIFIED status), caseFileId, dossierId."
        },
        {
          "name": "Dossier Package Url",
          "value": "dossier_package_url",
          "action": "Dossier Package Url",
          "description": "Returns the download URL for the full dossier package (PDF + evidence files). Requires: dossier_certify (CERTIFIED status), caseFileId, dossierId."
        },
        {
          "name": "Dossier Visibility",
          "value": "dossier_visibility",
          "action": "Dossier Visibility",
          "description": "Updates the visibility (public/private) of a certified dossier. Requires: dossier_certify (CERTIFIED status), caseFileId, dossierId."
        },
        {
          "name": "Delete Dossier",
          "value": "dossier_delete",
          "action": "Delete Dossier",
          "description": "Deletes a dossier. Available in DRAFT status (to discard before certification) or in CERTIFIED status (to permanently remove the certified dossier). Irreversible. Requires: caseFileId and dossierId."
        },
        {
          "name": "Certify Dossier Group",
          "value": "dossier_group_certify",
          "action": "Certify Dossier Group",
          "description": "Creates AND certifies a dossier from a single sealed evidence group in one call (express path). Requires: evidence_seal (CLOSED), case_file_create → caseFileId, evidence_group_create → evidenceGroupId. Generate a UUID v4 string for `id`. Returns dossierId with CERTIFYING status → poll until CERTIFIED."
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "dossier"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "notification_document_add",
      "options": [
        {
          "name": "Add Notification Document",
          "value": "notification_document_add",
          "action": "Add Notification Document",
          "description": "Performs the notification_document_add operation. Review the API documentation for full field details."
        },
        {
          "name": "Create Notification Request",
          "value": "notification_request_create",
          "action": "Create Notification Request",
          "description": "Creates a certified notification request. Requires: case_file_create → caseFileId. Generate a UUID v4 for `id`. Set language to en_GB or es_ES. Returns notificationRequestId. Add at least one receiver with notification_receiver_add before sending. IMPORTANT: The `content` field must be valid HTML — plain text without HTML tags will not render on the recipient landing page. Only the following HTML formats are supported: paragraphs (<p>), bold (<strong>), italic (<em>), unordered lists (<ul><li>), ordered lists (<ol><li>). Do not use other HTML tags or CSS. Avoid special typographic characters (em dashes, smart quotes) in `subject`; use standard ASCII equivalents (hyphen, straight quotes) instead."
        },
        {
          "name": "Send Notification Request",
          "value": "notification_request_send",
          "action": "Send Notification Request",
          "description": "Trigger delivery of a certified notification to all added recipients. Returns immediately — delivery is async. Poll notification_request_status until status is DELIVERED before retrieving certificates."
        },
        {
          "name": "Notification Request Status",
          "value": "notification_request_status",
          "action": "Notification Request Status",
          "description": "Checks the delivery status of a certified notification. Requires: notificationRequestId, caseFileId. Returns status (CREATING|DRAFT|IN_PROCESS|SENT|PARTIALLY_READ|FULLY_READ|PARTIALLY_ANSWERED|FULLY_ANSWERED). Poll until status is SENT or beyond. Do not call notification_certificate_get while status is CREATING, DRAFT, or IN_PROCESS."
        },
        {
          "name": "Add Notification Receiver",
          "value": "notification_receiver_add",
          "action": "Add Notification Receiver",
          "description": "Adds a recipient to a notification request. Requires: notification_request_create → notificationRequestId, case_file_create → caseFileId. The `id` can be a UUID v4 or custom string. Returns receiverId — save it for notification_certificate_get."
        },
        {
          "name": "Get Notification Certificate",
          "value": "notification_certificate_get",
          "action": "Get Notification Certificate",
          "description": "Creates or retrieves a PDF certificate for a specific notification receiver. Requires notification_request_send and notification_receiver_add. Generate a UUID v4 for `id` the first time and reuse that id when polling. This tool is idempotent: it first lists existing certificates for the receiver and, if `id` already exists, returns it instead of creating it again. If the certificate status is CERTIFIED, the response includes documentUrl when available. If it is CERTIFYING, poll this same tool with the same id."
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "notification"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "signature_group_create",
      "options": [
        {
          "name": "Create Signature Group",
          "value": "signature_group_create",
          "action": "Create Signature Group",
          "description": "Creates a signing order group for a CONFIGURABLE signature request. Types: 'Document' (groups documents into signing rounds — use its id as groupId in signature_request_add_document), 'Signatory' (groups signatories into signing rounds — use its id as groupId in signature_participant_create), 'DocumentSignatory' (links a specific document to a signing round, requires documentId). IMPORTANT — avoid empty groups: when a CONFIGURABLE request is created, the API automatically pre-creates one Document group and one Signatory group both at index:1. Always use these pre-existing index:1 groups for your first document and first signatory (retrieve their IDs with signature_group_list immediately after creating the request). Only call signature_group_create for the ADDITIONAL groups (index:2, 3…). Add participants with linkToAllDocuments:true so DocumentSignatory groups are auto-generated at the correct index. Adding participants without linkToAllDocuments leaves them unlinked to documents and signature_coordinate_set will fail with 'Signatory not found'."
        },
        {
          "name": "List Signature Group",
          "value": "signature_group_list",
          "action": "List Signature Group",
          "description": "Lists all signing order groups of a CONFIGURABLE signature request. Returns id, type (Document/Signatory/DocumentSignatory), index, and documentId for each group. Call immediately after signature_request_create to retrieve the pre-created index:1 group IDs before adding documents or participants."
        },
        {
          "name": "Create Signature Request",
          "value": "signature_request_create",
          "action": "Create Signature Request",
          "description": "Creates a new signature request in DRAFT status. Requires: case_file_create → caseFileId. Generate a UUID v4 for `id`. Set deadline as ISO 8601 datetime (max ~30 days ahead). Returns requestId. Add documents with signature_request_add_document and participants with signature_participant_create before activating."
        },
        {
          "name": "Get Signature Request",
          "value": "signature_request_get",
          "action": "Get Signature Request",
          "description": "Retrieves full details of a signature request. Requires: signature_request_create → requestId, case_file_create → caseFileId. Returns status, documents, participants, deadline, and history. Use to check overall process state."
        },
        {
          "name": "Cancel Signature Request",
          "value": "signature_request_cancel",
          "action": "Cancel Signature Request",
          "description": "Cancels an active signature request. Requires: activate_signature_request (ACTIVE status), requestId, caseFileId. Transitions to CANCELLED. Cannot be undone."
        },
        {
          "name": "Signature Request Add Document",
          "value": "signature_request_add_document",
          "action": "Signature Request Add Document",
          "description": "Adds a document to a DRAFT signature request. Requires: signature_request_create → requestId, case_file_create → caseFileId. Provide a string `id` for the document. Compute SHA-256 hex hash of the PDF before calling. Optional: pass `fileUrl` (a publicly accessible URL) to have the tool download and upload the file to S3 automatically — no separate PUT needed. If fileUrl is omitted, returns url (presigned S3 upload URL) for manual PUT. Cannot add documents after activate_signature_request is called. For CONFIGURABLE sequence: `groupId` must reference a Document type group (not Signatory or DocumentSignatory) — passing a wrong group type returns 'Signature group not found'."
        },
        {
          "name": "List Signature Document",
          "value": "signature_document_list",
          "action": "List Signature Document",
          "description": "Lists documents in a signature request with their signing status per document. Requires: signature_request_create → requestId, case_file_create → caseFileId. IMPORTANT: when called with documentId it returns participant signing status (PENDING = not yet signed), NOT document processing status. To check if documents reached READY_TO_SIGN (required before activate_signature_request), use signature_request_get instead. Post-activation: poll until document status === SIGNED before calling signature_certificate_get."
        },
        {
          "name": "Create Signature Participant",
          "value": "signature_participant_create",
          "action": "Create Signature Participant",
          "description": "Adds a participant (signatory, observer, or validator) to a DRAFT signature request. Requires: signature_request_add_document → documentId + file uploaded to S3, signature_request_create → requestId, case_file_create → caseFileId. Use role SIGNATORY for required signers, OBSERVER for read-only, VALIDATOR for approvers. For ADVANCED signatures, phonePrefix and phoneNumber are mandatory because the signer receives the OTP there; WhatsApp delivery is NOT currently supported for ADVANCED. For INTERPOSITION signatures, phone is optional, and WhatsApp sending is currently available only for this simple/interposition flow when the platform is configured to send a WhatsApp signing link. Returns signatoryId. Add at least one SIGNATORY before activating. For VALIDATOR role: do NOT include groupId or linkToAllDocuments — use assign_validator_to_signatory to link the validator to a specific signatory after creation."
        },
        {
          "name": "List Signature Participant",
          "value": "signature_participant_list",
          "action": "List Signature Participant",
          "description": "Lists all participants of a signature request. Requires: signature_request_create → requestId, case_file_create → caseFileId. Returns roles, contact details, and signing status."
        },
        {
          "name": "Assign Validator To Signatory",
          "value": "assign_validator_to_signatory",
          "action": "Assign Validator To Signatory",
          "description": "Assigns one or more validators to a specific signatory in a signature request. The validator must approve before the signatory can sign. Requires: signature_participant_create (validator) → validatorId in validatorIds array, signature_participant_create (signatory) → signatoryId, signature_request_create → requestId, case_file_create → caseFileId."
        },
        {
          "name": "Activate Signature Request",
          "value": "activate_signature_request",
          "action": "Activate Signature Request",
          "description": "Activates a signature request, transitioning from DRAFT to ACTIVE and sending signing invitations to all signatories. Do NOT call this immediately after uploading files. Activation preconditions: request is DRAFT; at least one SIGNATORY exists; every document has been uploaded to its presigned URL; backend processing has had time to complete for every uploaded document (use processed/READY_TO_SIGN from signature_request_get when exposed; otherwise wait after the successful PUT); and PDF documents have signature coordinates set for every required signatory. INTERPOSITION may send a simple signing link, including WhatsApp when available/configured; ADVANCED uses phonePrefix/phoneNumber for OTP and currently does not support WhatsApp delivery. IRREVERSIBLE: cannot add documents or participants after activation. ASYNC: after activation, poll signature_request_get until status is ACTIVE, then use signature_document_list with documentId to monitor signing; call signature_certificate_get only after the document is SIGNED."
        },
        {
          "name": "Set Signature Coordinate",
          "value": "signature_coordinate_set",
          "action": "Set Signature Coordinate",
          "description": "Sets the visual position of the signature field on a PDF document page. Required for PDF documents before activation, for both INTERPOSITION and ADVANCED signatures. Requires: signature_participant_create → signatoryId, signature_request_add_document → documentId, signature_request_create → requestId, case_file_create → caseFileId. Provide coordinates as array of {page (1-based), x (points from left), y (points from bottom)}. Set coordinates after the document has been uploaded and before activate_signature_request."
        },
        {
          "name": "Get Signature Certificate",
          "value": "signature_certificate_get",
          "action": "Get Signature Certificate",
          "description": "Retrieves the signed document certificate PDF. Requires: activate_signature_request (document fully SIGNED), signature_request_add_document → documentId, signature_request_create → requestId, case_file_create → caseFileId. Returns documentUrl (signed PDF certificate). ASYNC: poll until documentUrl is available."
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "signature"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "session_login",
      "options": [
        {
          "name": "Login Session",
          "value": "session_login",
          "action": "Login Session",
          "description": "Authenticate with EAD Enterprise Suite. Reads MCP_AUTH_EMAIL to discover the auth type (Password or OpenId) for that account. For Password accounts: uses MCP_AUTH_PASSWORD to obtain a session JWT. For OpenId accounts: starts an Azure AD device flow — on the FIRST call returns a browser link and code for the user to approve with Microsoft Authenticator; call session_login AGAIN after approving to complete authentication."
        },
        {
          "name": "Session Info",
          "value": "session_info",
          "action": "Session Info",
          "description": "Returns the authenticated user's session info including userId, session type (Password or OpenId), and for OpenId sessions: issuer, clientId, and scopes. Use this to retrieve the userId (UUID) required by case_file_list and other user-scoped operations. Prerequisites: a valid session (call session_login first if needed). Example: session_info() → { userId: '...uuid...', type: 'Password' }"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "session"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "use_case_list",
      "options": [
        {
          "name": "List Use Case",
          "value": "use_case_list",
          "action": "List Use Case",
          "description": "Lists available use cases for the account. Use cases define the allowed signature workflows and document types. Returns useCaseId values needed for signature_request_create."
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "useCase"
          ]
        }
      },
      "noDataExpression": true
    }
  ]

operations:
  [
    {
      "name": "Create Case File",
      "value": "case_file_create",
      "action": "Create Case File",
      "description": "Creates a new case file — the top-level container for all related operations (evidence, notifications, signatures, dossiers). Call this first before any other operation. Generate a UUID v4 for `id`. Returns caseFileId needed for all subsequent calls.",
      "resource": "caseFile"
    },
    {
      "name": "List Case File",
      "value": "case_file_list",
      "action": "List Case File",
      "description": "Lists all case files in your EAD Enterprise Suite account. Pass userId (from session_login or session_info) to scope results to your account. Returns paginated list with IDs, names, and status.",
      "resource": "caseFile"
    },
    {
      "name": "Get Case File",
      "value": "case_file_get",
      "action": "Get Case File",
      "description": "Retrieves details of a specific case file. Requires: caseFileId. Use to verify a case file exists before creating evidence groups, dossiers, or signature requests.",
      "resource": "caseFile"
    },
    {
      "name": "Create Evidence",
      "value": "evidence_create",
      "action": "Create Evidence",
      "description": "Registers a NEW evidence record inside an evidence group. Requires: evidence_group_create → evidenceGroupId, case_file_create → caseFileId. Generate a UUID v4 for `id`. Compute the SHA-256 hex hash of the file BEFORE calling. Normal INTERNAL flow: call evidence_create with custodyType INTERNAL and NO fileUrl; the API returns uploadFileUrl, a presigned S3 URL. You MUST PUT the exact file bytes to uploadFileUrl, then verify with evidence_get/evidence_list, and ONLY THEN call evidence_seal. Do not seal an evidence group until every INTERNAL evidence file has been uploaded. Convenience flow: if you pass `fileUrl` (public HTTPS, no redirects, under 1 GiB), this tool downloads that URL and PUTs the bytes to uploadFileUrl for you. EXTERNAL flow: use custodyType EXTERNAL only when you intentionally register hash-only evidence; still generate a fresh UUID for each evidence. If an INTERNAL evidence creation/upload failed and you want to retry as EXTERNAL, create a NEW evidence id; do not reuse an id whose outcome is unknown. WARNING: the API sometimes returns {code:'EvidenceCreateError'} even when the evidence was successfully persisted — always verify with evidence_list before retrying.",
      "resource": "evidence"
    },
    {
      "name": "List Evidence",
      "value": "evidence_list",
      "action": "List Evidence",
      "description": "Lists all evidence records in a specific evidence group. Requires: caseFileId and evidenceGroupId. Returns paginated list with IDs, titles, status, and timestamps.",
      "resource": "evidence"
    },
    {
      "name": "Seal Evidence",
      "value": "evidence_seal",
      "action": "Seal Evidence",
      "description": "Seal and certify an evidence group. Closes the group to new additions and triggers async timestamping. Returns immediately — the group transitions OPEN → CLOSING → CLOSED. Poll evidence_group_list until status is CLOSED before linking to a dossier.",
      "resource": "evidence"
    },
    {
      "name": "Get Evidence",
      "value": "evidence_get",
      "action": "Get Evidence",
      "description": "Retrieves a specific evidence record. Requires: evidence_create → evidenceId, evidence_group_create → evidenceGroupId, case_file_create → caseFileId. Returns status (COMPLETED|IN_PROCESS|ERROR), hash, and tspTimestamp when certified.",
      "resource": "evidence"
    },
    {
      "name": "Create Evidence Group",
      "value": "evidence_group_create",
      "action": "Create Evidence Group",
      "description": "Creates an evidence group inside a case file. Requires: case_file_create → caseFileId. Generate a UUID v4 for `id`. Set evidenceType to FILE, PHOTO, VIDEO, or WEB_PLUGIN. Returns evidenceGroupId. One group can contain multiple evidence records.",
      "resource": "evidence"
    },
    {
      "name": "List Evidence Group",
      "value": "evidence_group_list",
      "action": "List Evidence Group",
      "description": "Lists all evidence groups in a case file with their current status (OPEN, CLOSING, CLOSED). Use to find an existing group or check which groups are ready for sealing. Requires: caseFileId.",
      "resource": "evidence"
    },
    {
      "name": "Initiate Large Evidence Upload",
      "value": "large_evidence_upload_initiate",
      "action": "Initiate Large Evidence Upload",
      "description": "Performs the large_evidence_upload_initiate operation against the GoCertius API. Review the API documentation for full field details.",
      "resource": "evidence"
    },
    {
      "name": "Complete Large Evidence Upload",
      "value": "large_evidence_upload_complete",
      "action": "Complete Large Evidence Upload",
      "description": "Finalize a multipart evidence upload and register the evidence in the group. Returns immediately — the evidence transitions asynchronously to COMPLETED. Poll evidence_list until status is COMPLETED before sealing the group.",
      "resource": "evidence"
    },
    {
      "name": "Link Dossier Evidence",
      "value": "dossier_evidence_link",
      "action": "Link Dossier Evidence",
      "description": "Links evidence items from a sealed group to a dossier. Requires: dossier_create → dossierId, evidence_seal (CLOSED), case_file_create → caseFileId. Pass the ids array of evidence UUIDs. Can be called multiple times for evidence from different case files.",
      "resource": "dossierEvidence"
    },
    {
      "name": "Dossier Evidence List To Link",
      "value": "dossier_evidence_list_to_link",
      "action": "Dossier Evidence List To Link",
      "description": "Lists evidence items available to be linked to a dossier (CLOSED groups not yet linked). Requires: caseFileId and dossierId.",
      "resource": "dossierEvidence"
    },
    {
      "name": "List Dossier Evidence",
      "value": "dossier_evidence_list",
      "action": "List Dossier Evidence",
      "description": "Lists all evidence items linked to a dossier. Requires: caseFileId and dossierId.",
      "resource": "dossierEvidence"
    },
    {
      "name": "Get Dossier Evidence",
      "value": "dossier_evidence_get",
      "action": "Get Dossier Evidence",
      "description": "Retrieves details of a specific evidence item linked to a dossier. Requires: caseFileId, dossierId, evidenceId.",
      "resource": "dossierEvidence"
    },
    {
      "name": "Delete Dossier Evidence",
      "value": "dossier_evidence_delete",
      "action": "Delete Dossier Evidence",
      "description": "Removes an evidence item from a dossier. Only available while dossier is in DRAFT status. Requires: caseFileId, dossierId, evidenceId.",
      "resource": "dossierEvidence"
    },
    {
      "name": "Create Dossier",
      "value": "dossier_create",
      "action": "Create Dossier",
      "description": "Creates a dossier to aggregate certified evidence groups into a single tamper-evident PDF. Requires: case_file_create → caseFileId. Evidence groups must be in CLOSED status before linking. Generate a UUID v4 string for `id`. Returns dossierId. After creation, link evidence with dossier_evidence_link, then certify with dossier_certify.",
      "resource": "dossier"
    },
    {
      "name": "Update Dossier",
      "value": "dossier_update",
      "action": "Update Dossier",
      "description": "Updates the metadata of an existing dossier. Requires: dossier_create → dossierId, caseFileId. Only available while dossier is in DRAFT status.",
      "resource": "dossier"
    },
    {
      "name": "Certify Dossier",
      "value": "dossier_certify",
      "action": "Certify Dossier",
      "description": "Certifies a dossier, generating a tamper-evident PDF and locking all linked evidence. Requires: dossier_create → dossierId, dossier_evidence_link (evidence linked), case_file_create → caseFileId. ASYNC: transitions DRAFT → CERTIFYING → CERTIFIED. Poll dossier_list until dossierId status === CERTIFIED.",
      "resource": "dossier"
    },
    {
      "name": "List Dossier",
      "value": "dossier_list",
      "action": "List Dossier",
      "description": "Lists all dossiers in a case file. Requires: caseFileId. Returns paginated list with IDs, names, status, and creation dates. Use to monitor certification progress — poll until status: CERTIFIED.",
      "resource": "dossier"
    },
    {
      "name": "Get Dossier",
      "value": "dossier_get",
      "action": "Get Dossier",
      "description": "Retrieves full details of a specific dossier including status, linked evidence, and download URLs. Requires: caseFileId and dossierId.",
      "resource": "dossier"
    },
    {
      "name": "List Dossier Template",
      "value": "dossier_template_list",
      "action": "List Dossier Template",
      "description": "Lists available dossier templates. No prerequisites. Returns template IDs and their translations per language. Use the returned id as dossierTemplateId in dossier_create.",
      "resource": "dossier"
    },
    {
      "name": "Preview Dossier",
      "value": "dossier_preview",
      "action": "Preview Dossier",
      "description": "Returns an HTML preview URL of a dossier before certification. Requires: caseFileId and dossierId.",
      "resource": "dossier"
    },
    {
      "name": "Dossier Document Url",
      "value": "dossier_document_url",
      "action": "Dossier Document Url",
      "description": "Returns the download URL for the certified dossier PDF. Requires: dossier_certify (CERTIFIED status), caseFileId, dossierId.",
      "resource": "dossier"
    },
    {
      "name": "Dossier Package Url",
      "value": "dossier_package_url",
      "action": "Dossier Package Url",
      "description": "Returns the download URL for the full dossier package (PDF + evidence files). Requires: dossier_certify (CERTIFIED status), caseFileId, dossierId.",
      "resource": "dossier"
    },
    {
      "name": "Dossier Visibility",
      "value": "dossier_visibility",
      "action": "Dossier Visibility",
      "description": "Updates the visibility (public/private) of a certified dossier. Requires: dossier_certify (CERTIFIED status), caseFileId, dossierId.",
      "resource": "dossier"
    },
    {
      "name": "Delete Dossier",
      "value": "dossier_delete",
      "action": "Delete Dossier",
      "description": "Deletes a dossier. Available in DRAFT status (to discard before certification) or in CERTIFIED status (to permanently remove the certified dossier). Irreversible. Requires: caseFileId and dossierId.",
      "resource": "dossier"
    },
    {
      "name": "Certify Dossier Group",
      "value": "dossier_group_certify",
      "action": "Certify Dossier Group",
      "description": "Creates AND certifies a dossier from a single sealed evidence group in one call (express path). Requires: evidence_seal (CLOSED), case_file_create → caseFileId, evidence_group_create → evidenceGroupId. Generate a UUID v4 string for `id`. Returns dossierId with CERTIFYING status → poll until CERTIFIED.",
      "resource": "dossier"
    },
    {
      "name": "Add Notification Document",
      "value": "notification_document_add",
      "action": "Add Notification Document",
      "description": "Performs the notification_document_add operation. Review the API documentation for full field details.",
      "resource": "notification"
    },
    {
      "name": "Create Notification Request",
      "value": "notification_request_create",
      "action": "Create Notification Request",
      "description": "Creates a certified notification request. Requires: case_file_create → caseFileId. Generate a UUID v4 for `id`. Set language to en_GB or es_ES. Returns notificationRequestId. Add at least one receiver with notification_receiver_add before sending. IMPORTANT: The `content` field must be valid HTML — plain text without HTML tags will not render on the recipient landing page. Only the following HTML formats are supported: paragraphs (<p>), bold (<strong>), italic (<em>), unordered lists (<ul><li>), ordered lists (<ol><li>). Do not use other HTML tags or CSS. Avoid special typographic characters (em dashes, smart quotes) in `subject`; use standard ASCII equivalents (hyphen, straight quotes) instead.",
      "resource": "notification"
    },
    {
      "name": "Send Notification Request",
      "value": "notification_request_send",
      "action": "Send Notification Request",
      "description": "Trigger delivery of a certified notification to all added recipients. Returns immediately — delivery is async. Poll notification_request_status until status is DELIVERED before retrieving certificates.",
      "resource": "notification"
    },
    {
      "name": "Notification Request Status",
      "value": "notification_request_status",
      "action": "Notification Request Status",
      "description": "Checks the delivery status of a certified notification. Requires: notificationRequestId, caseFileId. Returns status (CREATING|DRAFT|IN_PROCESS|SENT|PARTIALLY_READ|FULLY_READ|PARTIALLY_ANSWERED|FULLY_ANSWERED). Poll until status is SENT or beyond. Do not call notification_certificate_get while status is CREATING, DRAFT, or IN_PROCESS.",
      "resource": "notification"
    },
    {
      "name": "Add Notification Receiver",
      "value": "notification_receiver_add",
      "action": "Add Notification Receiver",
      "description": "Adds a recipient to a notification request. Requires: notification_request_create → notificationRequestId, case_file_create → caseFileId. The `id` can be a UUID v4 or custom string. Returns receiverId — save it for notification_certificate_get.",
      "resource": "notification"
    },
    {
      "name": "Get Notification Certificate",
      "value": "notification_certificate_get",
      "action": "Get Notification Certificate",
      "description": "Creates or retrieves a PDF certificate for a specific notification receiver. Requires notification_request_send and notification_receiver_add. Generate a UUID v4 for `id` the first time and reuse that id when polling. This tool is idempotent: it first lists existing certificates for the receiver and, if `id` already exists, returns it instead of creating it again. If the certificate status is CERTIFIED, the response includes documentUrl when available. If it is CERTIFYING, poll this same tool with the same id.",
      "resource": "notification"
    },
    {
      "name": "Create Signature Group",
      "value": "signature_group_create",
      "action": "Create Signature Group",
      "description": "Creates a signing order group for a CONFIGURABLE signature request. Types: 'Document' (groups documents into signing rounds — use its id as groupId in signature_request_add_document), 'Signatory' (groups signatories into signing rounds — use its id as groupId in signature_participant_create), 'DocumentSignatory' (links a specific document to a signing round, requires documentId). IMPORTANT — avoid empty groups: when a CONFIGURABLE request is created, the API automatically pre-creates one Document group and one Signatory group both at index:1. Always use these pre-existing index:1 groups for your first document and first signatory (retrieve their IDs with signature_group_list immediately after creating the request). Only call signature_group_create for the ADDITIONAL groups (index:2, 3…). Add participants with linkToAllDocuments:true so DocumentSignatory groups are auto-generated at the correct index. Adding participants without linkToAllDocuments leaves them unlinked to documents and signature_coordinate_set will fail with 'Signatory not found'.",
      "resource": "signature"
    },
    {
      "name": "List Signature Group",
      "value": "signature_group_list",
      "action": "List Signature Group",
      "description": "Lists all signing order groups of a CONFIGURABLE signature request. Returns id, type (Document/Signatory/DocumentSignatory), index, and documentId for each group. Call immediately after signature_request_create to retrieve the pre-created index:1 group IDs before adding documents or participants.",
      "resource": "signature"
    },
    {
      "name": "Create Signature Request",
      "value": "signature_request_create",
      "action": "Create Signature Request",
      "description": "Creates a new signature request in DRAFT status. Requires: case_file_create → caseFileId. Generate a UUID v4 for `id`. Set deadline as ISO 8601 datetime (max ~30 days ahead). Returns requestId. Add documents with signature_request_add_document and participants with signature_participant_create before activating.",
      "resource": "signature"
    },
    {
      "name": "Get Signature Request",
      "value": "signature_request_get",
      "action": "Get Signature Request",
      "description": "Retrieves full details of a signature request. Requires: signature_request_create → requestId, case_file_create → caseFileId. Returns status, documents, participants, deadline, and history. Use to check overall process state.",
      "resource": "signature"
    },
    {
      "name": "Cancel Signature Request",
      "value": "signature_request_cancel",
      "action": "Cancel Signature Request",
      "description": "Cancels an active signature request. Requires: activate_signature_request (ACTIVE status), requestId, caseFileId. Transitions to CANCELLED. Cannot be undone.",
      "resource": "signature"
    },
    {
      "name": "Signature Request Add Document",
      "value": "signature_request_add_document",
      "action": "Signature Request Add Document",
      "description": "Adds a document to a DRAFT signature request. Requires: signature_request_create → requestId, case_file_create → caseFileId. Provide a string `id` for the document. Compute SHA-256 hex hash of the PDF before calling. Optional: pass `fileUrl` (a publicly accessible URL) to have the tool download and upload the file to S3 automatically — no separate PUT needed. If fileUrl is omitted, returns url (presigned S3 upload URL) for manual PUT. Cannot add documents after activate_signature_request is called. For CONFIGURABLE sequence: `groupId` must reference a Document type group (not Signatory or DocumentSignatory) — passing a wrong group type returns 'Signature group not found'.",
      "resource": "signature"
    },
    {
      "name": "List Signature Document",
      "value": "signature_document_list",
      "action": "List Signature Document",
      "description": "Lists documents in a signature request with their signing status per document. Requires: signature_request_create → requestId, case_file_create → caseFileId. IMPORTANT: when called with documentId it returns participant signing status (PENDING = not yet signed), NOT document processing status. To check if documents reached READY_TO_SIGN (required before activate_signature_request), use signature_request_get instead. Post-activation: poll until document status === SIGNED before calling signature_certificate_get.",
      "resource": "signature"
    },
    {
      "name": "Create Signature Participant",
      "value": "signature_participant_create",
      "action": "Create Signature Participant",
      "description": "Adds a participant (signatory, observer, or validator) to a DRAFT signature request. Requires: signature_request_add_document → documentId + file uploaded to S3, signature_request_create → requestId, case_file_create → caseFileId. Use role SIGNATORY for required signers, OBSERVER for read-only, VALIDATOR for approvers. For ADVANCED signatures, phonePrefix and phoneNumber are mandatory because the signer receives the OTP there; WhatsApp delivery is NOT currently supported for ADVANCED. For INTERPOSITION signatures, phone is optional, and WhatsApp sending is currently available only for this simple/interposition flow when the platform is configured to send a WhatsApp signing link. Returns signatoryId. Add at least one SIGNATORY before activating. For VALIDATOR role: do NOT include groupId or linkToAllDocuments — use assign_validator_to_signatory to link the validator to a specific signatory after creation.",
      "resource": "signature"
    },
    {
      "name": "List Signature Participant",
      "value": "signature_participant_list",
      "action": "List Signature Participant",
      "description": "Lists all participants of a signature request. Requires: signature_request_create → requestId, case_file_create → caseFileId. Returns roles, contact details, and signing status.",
      "resource": "signature"
    },
    {
      "name": "Assign Validator To Signatory",
      "value": "assign_validator_to_signatory",
      "action": "Assign Validator To Signatory",
      "description": "Assigns one or more validators to a specific signatory in a signature request. The validator must approve before the signatory can sign. Requires: signature_participant_create (validator) → validatorId in validatorIds array, signature_participant_create (signatory) → signatoryId, signature_request_create → requestId, case_file_create → caseFileId.",
      "resource": "signature"
    },
    {
      "name": "Activate Signature Request",
      "value": "activate_signature_request",
      "action": "Activate Signature Request",
      "description": "Activates a signature request, transitioning from DRAFT to ACTIVE and sending signing invitations to all signatories. Do NOT call this immediately after uploading files. Activation preconditions: request is DRAFT; at least one SIGNATORY exists; every document has been uploaded to its presigned URL; backend processing has had time to complete for every uploaded document (use processed/READY_TO_SIGN from signature_request_get when exposed; otherwise wait after the successful PUT); and PDF documents have signature coordinates set for every required signatory. INTERPOSITION may send a simple signing link, including WhatsApp when available/configured; ADVANCED uses phonePrefix/phoneNumber for OTP and currently does not support WhatsApp delivery. IRREVERSIBLE: cannot add documents or participants after activation. ASYNC: after activation, poll signature_request_get until status is ACTIVE, then use signature_document_list with documentId to monitor signing; call signature_certificate_get only after the document is SIGNED.",
      "resource": "signature"
    },
    {
      "name": "Set Signature Coordinate",
      "value": "signature_coordinate_set",
      "action": "Set Signature Coordinate",
      "description": "Sets the visual position of the signature field on a PDF document page. Required for PDF documents before activation, for both INTERPOSITION and ADVANCED signatures. Requires: signature_participant_create → signatoryId, signature_request_add_document → documentId, signature_request_create → requestId, case_file_create → caseFileId. Provide coordinates as array of {page (1-based), x (points from left), y (points from bottom)}. Set coordinates after the document has been uploaded and before activate_signature_request.",
      "resource": "signature"
    },
    {
      "name": "Get Signature Certificate",
      "value": "signature_certificate_get",
      "action": "Get Signature Certificate",
      "description": "Retrieves the signed document certificate PDF. Requires: activate_signature_request (document fully SIGNED), signature_request_add_document → documentId, signature_request_create → requestId, case_file_create → caseFileId. Returns documentUrl (signed PDF certificate). ASYNC: poll until documentUrl is available.",
      "resource": "signature"
    },
    {
      "name": "Login Session",
      "value": "session_login",
      "action": "Login Session",
      "description": "Authenticate with EAD Enterprise Suite. Reads MCP_AUTH_EMAIL to discover the auth type (Password or OpenId) for that account. For Password accounts: uses MCP_AUTH_PASSWORD to obtain a session JWT. For OpenId accounts: starts an Azure AD device flow — on the FIRST call returns a browser link and code for the user to approve with Microsoft Authenticator; call session_login AGAIN after approving to complete authentication.",
      "resource": "session"
    },
    {
      "name": "Session Info",
      "value": "session_info",
      "action": "Session Info",
      "description": "Returns the authenticated user's session info including userId, session type (Password or OpenId), and for OpenId sessions: issuer, clientId, and scopes. Use this to retrieve the userId (UUID) required by case_file_list and other user-scoped operations. Prerequisites: a valid session (call session_login first if needed). Example: session_info() → { userId: '...uuid...', type: 'Password' }",
      "resource": "session"
    },
    {
      "name": "List Use Case",
      "value": "use_case_list",
      "action": "List Use Case",
      "description": "Lists available use cases for the account. Use cases define the allowed signature workflows and document types. Returns useCaseId values needed for signature_request_create.",
      "resource": "useCase"
    }
  ]

npm_readme:
  # EAD Enterprise Suite — n8n connector

  > MCP server for EAD Enterprise Suite - signatures, evidence, notifications, dossiers via AI agents.

  Install this connector and use EAD Enterprise Suite operations as steps inside any n8n workflow. Each operation maps to one capability of the underlying EAD Enterprise Suite platform.

  ## Install (self-hosted n8n)

  ```bash
  npm install @g-digital/n8n-nodes-ead-enterprise-suite
  ```

  Then restart n8n. The node will appear in the Nodes panel under "EAD Enterprise Suite".

  ## Using with n8n AI Agent

  For AI-driven automation, configure an **n8n AI Agent node** with the following system prompt. It covers all lifecycle workflows: evidence creation, certified notifications, signature processes, dossier certification.

  **→ Full system prompt and workflow guide:** [`@g-digital/n8n-agent-system-prompt`](https://www.npmjs.com/package/@g-digital/mcp-gocertius) — see the `docs/n8n-agent-workflows/gocertius-ead-system-prompt.md` in [MCP_Market_Distribution](https://github.com/g-digital-by-Garrigues/MCP_Market_Distribution/blob/main/docs/n8n-agent-workflows/gocertius-ead-system-prompt.md).

  ### Quick system prompt snippet

  Paste this into your AI Agent node's **System Message**:

  ```
  You are a Digital Trust assistant using the EAD Enterprise Suite n8n connector.
  UUID generation: generate UUID v4 for all `id` fields you must supply.
  IDs from responses: never invent path parameters — always use values returned by previous tool calls.
  Async operations: after evidence_seal, dossier_certify, signature activation — poll the corresponding list/status tool until the terminal state is reached before proceeding.
  File uploads: when a tool returns uploadFileUrl or url, PUT the file bytes there with a separate HTTP Request node before calling the next step.
  See the full lifecycle guide at: https://github.com/g-digital-by-Garrigues/MCP_Market_Distribution/blob/main/docs/n8n-agent-workflows/gocertius-ead-system-prompt.md
  ```

  ## Operations

  | Operation | Description |
  |---|---|
  | `evidence_create` | Registers a NEW evidence record inside an evidence group. Requires: evidence_group_create → evidenceGroupId, case_file_create → caseFileId. Generate a UUID v4 for `id`. Compute the SHA-256 hex hash of the file BEFORE calling. Normal INTERNAL flow: call evidence_create with custodyType INTERNAL and NO fileUrl; the API returns uploadFileUrl, a presigned S3 URL. You MUST PUT the exact file bytes to uploadFileUrl, then verify with evidence_get/evidence_list, and ONLY THEN call evidence_seal. Do not seal an evidence group until every INTERNAL evidence file has been uploaded. Convenience flow: if you pass `fileUrl` (public HTTPS, no redirects, under 1 GiB), this tool downloads that URL and PUTs the bytes to uploadFileUrl for you. EXTERNAL flow: use custodyType EXTERNAL only when you intentionally register hash-only evidence; still generate a fresh UUID for each evidence. If an INTERNAL evidence creation/upload failed and you want to retry as EXTERNAL, create a NEW evidence id; do not reuse an id whose outcome is unknown. WARNING: the API sometimes returns {code:'EvidenceCreateError'} even when the evidence was successfully persisted — always verify with evidence_list before retrying. |
  | `evidence_list` | Lists all evidence records in a specific evidence group. Requires: caseFileId and evidenceGroupId. Returns paginated list with IDs, titles, status, and timestamps. |
  | `evidence_seal` | Seal and certify an evidence group. Closes the group to new additions and triggers async timestamping. Returns immediately — the group transitions OPEN → CLOSING → CLOSED. Poll evidence_group_list until status is CLOSED before linking to a dossier. |
  | `evidence_get` | Retrieves a specific evidence record. Requires: evidence_create → evidenceId, evidence_group_create → evidenceGroupId, case_file_create → caseFileId. Returns status (COMPLETED|IN_PROCESS|ERROR), hash, and tspTimestamp when certified. |
  | `evidence_group_create` | Creates an evidence group inside a case file. Requires: case_file_create → caseFileId. Generate a UUID v4 for `id`. Set evidenceType to FILE, PHOTO, VIDEO, or WEB_PLUGIN. Returns evidenceGroupId. One group can contain multiple evidence records. |
  | `evidence_group_list` | Lists all evidence groups in a case file with their current status (OPEN, CLOSING, CLOSED). Use to find an existing group or check which groups are ready for sealing. Requires: caseFileId. |
  | `dossier_create` | Creates a dossier to aggregate certified evidence groups into a single tamper-evident PDF. Requires: case_file_create → caseFileId. Evidence groups must be in CLOSED status before linking. Generate a UUID v4 string for `id`. Returns dossierId. After creation, link evidence with dossier_evidence_link, then certify with dossier_certify. |
  | `dossier_update` | Updates the metadata of an existing dossier. Requires: dossier_create → dossierId, caseFileId. Only available while dossier is in DRAFT status. |
  | `dossier_certify` | Certifies a dossier, generating a tamper-evident PDF and locking all linked evidence. Requires: dossier_create → dossierId, dossier_evidence_link (evidence linked), case_file_create → caseFileId. ASYNC: transitions DRAFT → CERTIFYING → CERTIFIED. Poll dossier_list until dossierId status === CERTIFIED. |
  | `dossier_list` | Lists all dossiers in a case file. Requires: caseFileId. Returns paginated list with IDs, names, status, and creation dates. Use to monitor certification progress — poll until status: CERTIFIED. |
  | `dossier_get` | Retrieves full details of a specific dossier including status, linked evidence, and download URLs. Requires: caseFileId and dossierId. |
  | `dossier_template_list` | Lists available dossier templates. No prerequisites. Returns template IDs and their translations per language. Use the returned id as dossierTemplateId in dossier_create. |
  | `dossier_preview` | Returns an HTML preview URL of a dossier before certification. Requires: caseFileId and dossierId. |
  | `dossier_document_url` | Returns the download URL for the certified dossier PDF. Requires: dossier_certify (CERTIFIED status), caseFileId, dossierId. |
  | `dossier_package_url` | Returns the download URL for the full dossier package (PDF + evidence files). Requires: dossier_certify (CERTIFIED status), caseFileId, dossierId. |
  | `dossier_visibility` | Updates the visibility (public/private) of a certified dossier. Requires: dossier_certify (CERTIFIED status), caseFileId, dossierId. |
  | `dossier_delete` | Deletes a dossier. Available in DRAFT status (to discard before certification) or in CERTIFIED status (to permanently remove the certified dossier). Irreversible. Requires: caseFileId and dossierId. |
  | `dossier_group_certify` | Creates AND certifies a dossier from a single sealed evidence group in one call (express path). Requires: evidence_seal (CLOSED), case_file_create → caseFileId, evidence_group_create → evidenceGroupId. Generate a UUID v4 string for `id`. Returns dossierId with CERTIFYING status → poll until CERTIFIED. |
  | `dossier_evidence_link` | Links evidence items from a sealed group to a dossier. Requires: dossier_create → dossierId, evidence_seal (CLOSED), case_file_create → caseFileId. Pass the ids array of evidence UUIDs. Can be called multiple times for evidence from different case files. |
  | `dossier_evidence_list_to_link` | Lists evidence items available to be linked to a dossier (CLOSED groups not yet linked). Requires: caseFileId and dossierId. |
  | `dossier_evidence_list` | Lists all evidence items linked to a dossier. Requires: caseFileId and dossierId. |
  | `dossier_evidence_get` | Retrieves details of a specific evidence item linked to a dossier. Requires: caseFileId, dossierId, evidenceId. |
  | `dossier_evidence_delete` | Removes an evidence item from a dossier. Only available while dossier is in DRAFT status. Requires: caseFileId, dossierId, evidenceId. |
  | `notification_document_add` | Performs the notification_document_add operation. Review the API documentation for full field details. |
  | `notification_request_create` | Creates a certified notification request. Requires: case_file_create → caseFileId. Generate a UUID v4 for `id`. Set language to en_GB or es_ES. Returns notificationRequestId. Add at least one receiver with notification_receiver_add before sending. IMPORTANT: The `content` field must be valid HTML — plain text without HTML tags will not render on the recipient landing page. Only the following HTML formats are supported: paragraphs (<p>), bold (<strong>), italic (<em>), unordered lists (<ul><li>), ordered lists (<ol><li>). Do not use other HTML tags or CSS. Avoid special typographic characters (em dashes, smart quotes) in `subject`; use standard ASCII equivalents (hyphen, straight quotes) instead. |
  | `notification_request_send` | Trigger delivery of a certified notification to all added recipients. Returns immediately — delivery is async. Poll notification_request_status until status is DELIVERED before retrieving certificates. |
  | `notification_request_status` | Checks the delivery status of a certified notification. Requires: notificationRequestId, caseFileId. Returns status (CREATING|DRAFT|IN_PROCESS|SENT|PARTIALLY_READ|FULLY_READ|PARTIALLY_ANSWERED|FULLY_ANSWERED). Poll until status is SENT or beyond. Do not call notification_certificate_get while status is CREATING, DRAFT, or IN_PROCESS. |
  | `notification_receiver_add` | Adds a recipient to a notification request. Requires: notification_request_create → notificationRequestId, case_file_create → caseFileId. The `id` can be a UUID v4 or custom string. Returns receiverId — save it for notification_certificate_get. |
  | `notification_certificate_get` | Creates or retrieves a PDF certificate for a specific notification receiver. Requires notification_request_send and notification_receiver_add. Generate a UUID v4 for `id` the first time and reuse that id when polling. This tool is idempotent: it first lists existing certificates for the receiver and, if `id` already exists, returns it instead of creating it again. If the certificate status is CERTIFIED, the response includes documentUrl when available. If it is CERTIFYING, poll this same tool with the same id. |
  | `case_file_create` | Creates a new case file — the top-level container for all related operations (evidence, notifications, signatures, dossiers). Call this first before any other operation. Generate a UUID v4 for `id`. Returns caseFileId needed for all subsequent calls. |
  | `case_file_list` | Lists all case files in your EAD Enterprise Suite account. Pass userId (from session_login or session_info) to scope results to your account. Returns paginated list with IDs, names, and status. |
  | `case_file_get` | Retrieves details of a specific case file. Requires: caseFileId. Use to verify a case file exists before creating evidence groups, dossiers, or signature requests. |
  | `session_login` | Authenticate with EAD Enterprise Suite. Reads MCP_AUTH_EMAIL to discover the auth type (Password or OpenId) for that account. For Password accounts: uses MCP_AUTH_PASSWORD to obtain a session JWT. For OpenId accounts: starts an Azure AD device flow — on the FIRST call returns a browser link and code for the user to approve with Microsoft Authenticator; call session_login AGAIN after approving to complete authentication. |
  | `session_info` | Returns the authenticated user's session info including userId, session type (Password or OpenId), and for OpenId sessions: issuer, clientId, and scopes. Use this to retrieve the userId (UUID) required by case_file_list and other user-scoped operations. Prerequisites: a valid session (call session_login first if needed). Example: session_info() → { userId: '...uuid...', type: 'Password' } |
  | `use_case_list` | Lists available use cases for the account. Use cases define the allowed signature workflows and document types. Returns useCaseId values needed for signature_request_create. |
  | `signature_group_create` | Creates a signing order group for a CONFIGURABLE signature request. Types: 'Document' (groups documents into signing rounds — use its id as groupId in signature_request_add_document), 'Signatory' (groups signatories into signing rounds — use its id as groupId in signature_participant_create), 'DocumentSignatory' (links a specific document to a signing round, requires documentId). IMPORTANT — avoid empty groups: when a CONFIGURABLE request is created, the API automatically pre-creates one Document group and one Signatory group both at index:1. Always use these pre-existing index:1 groups for your first document and first signatory (retrieve their IDs with signature_group_list immediately after creating the request). Only call signature_group_create for the ADDITIONAL groups (index:2, 3…). Add participants with linkToAllDocuments:true so DocumentSignatory groups are auto-generated at the correct index. Adding participants without linkToAllDocuments leaves them unlinked to documents and signature_coordinate_set will fail with 'Signatory not found'. |
  | `signature_group_list` | Lists all signing order groups of a CONFIGURABLE signature request. Returns id, type (Document/Signatory/DocumentSignatory), index, and documentId for each group. Call immediately after signature_request_create to retrieve the pre-created index:1 group IDs before adding documents or participants. |
  | `signature_request_create` | Creates a new signature request in DRAFT status. Requires: case_file_create → caseFileId. Generate a UUID v4 for `id`. Set deadline as ISO 8601 datetime (max ~30 days ahead). Returns requestId. Add documents with signature_request_add_document and participants with signature_participant_create before activating. |
  | `signature_request_get` | Retrieves full details of a signature request. Requires: signature_request_create → requestId, case_file_create → caseFileId. Returns status, documents, participants, deadline, and history. Use to check overall process state. |
  | `signature_request_cancel` | Cancels an active signature request. Requires: activate_signature_request (ACTIVE status), requestId, caseFileId. Transitions to CANCELLED. Cannot be undone. |
  | `signature_request_add_document` | Adds a document to a DRAFT signature request. Requires: signature_request_create → requestId, case_file_create → caseFileId. Provide a string `id` for the document. Compute SHA-256 hex hash of the PDF before calling. Optional: pass `fileUrl` (a publicly accessible URL) to have the tool download and upload the file to S3 automatically — no separate PUT needed. If fileUrl is omitted, returns url (presigned S3 upload URL) for manual PUT. Cannot add documents after activate_signature_request is called. For CONFIGURABLE sequence: `groupId` must reference a Document type group (not Signatory or DocumentSignatory) — passing a wrong group type returns 'Signature group not found'. |
  | `signature_document_list` | Lists documents in a signature request with their signing status per document. Requires: signature_request_create → requestId, case_file_create → caseFileId. IMPORTANT: when called with documentId it returns participant signing status (PENDING = not yet signed), NOT document processing status. To check if documents reached READY_TO_SIGN (required before activate_signature_request), use signature_request_get instead. Post-activation: poll until document status === SIGNED before calling signature_certificate_get. |
  | `signature_participant_create` | Adds a participant (signatory, observer, or validator) to a DRAFT signature request. Requires: signature_request_add_document → documentId + file uploaded to S3, signature_request_create → requestId, case_file_create → caseFileId. Use role SIGNATORY for required signers, OBSERVER for read-only, VALIDATOR for approvers. For ADVANCED signatures, phonePrefix and phoneNumber are mandatory because the signer receives the OTP there; WhatsApp delivery is NOT currently supported for ADVANCED. For INTERPOSITION signatures, phone is optional, and WhatsApp sending is currently available only for this simple/interposition flow when the platform is configured to send a WhatsApp signing link. Returns signatoryId. Add at least one SIGNATORY before activating. For VALIDATOR role: do NOT include groupId or linkToAllDocuments — use assign_validator_to_signatory to link the validator to a specific signatory after creation. |
  | `signature_participant_list` | Lists all participants of a signature request. Requires: signature_request_create → requestId, case_file_create → caseFileId. Returns roles, contact details, and signing status. |
  | `assign_validator_to_signatory` | Assigns one or more validators to a specific signatory in a signature request. The validator must approve before the signatory can sign. Requires: signature_participant_create (validator) → validatorId in validatorIds array, signature_participant_create (signatory) → signatoryId, signature_request_create → requestId, case_file_create → caseFileId. |
  | `activate_signature_request` | Activates a signature request, transitioning from DRAFT to ACTIVE and sending signing invitations to all signatories. Do NOT call this immediately after uploading files. Activation preconditions: request is DRAFT; at least one SIGNATORY exists; every document has been uploaded to its presigned URL; backend processing has had time to complete for every uploaded document (use processed/READY_TO_SIGN from signature_request_get when exposed; otherwise wait after the successful PUT); and PDF documents have signature coordinates set for every required signatory. INTERPOSITION may send a simple signing link, including WhatsApp when available/configured; ADVANCED uses phonePrefix/phoneNumber for OTP and currently does not support WhatsApp delivery. IRREVERSIBLE: cannot add documents or participants after activation. ASYNC: after activation, poll signature_request_get until status is ACTIVE, then use signature_document_list with documentId to monitor signing; call signature_certificate_get only after the document is SIGNED. |
  | `signature_coordinate_set` | Sets the visual position of the signature field on a PDF document page. Required for PDF documents before activation, for both INTERPOSITION and ADVANCED signatures. Requires: signature_participant_create → signatoryId, signature_request_add_document → documentId, signature_request_create → requestId, case_file_create → caseFileId. Provide coordinates as array of {page (1-based), x (points from left), y (points from bottom)}. Set coordinates after the document has been uploaded and before activate_signature_request. |
  | `signature_certificate_get` | Retrieves the signed document certificate PDF. Requires: activate_signature_request (document fully SIGNED), signature_request_add_document → documentId, signature_request_create → requestId, case_file_create → caseFileId. Returns documentUrl (signed PDF certificate). ASYNC: poll until documentUrl is available. |
  | `large_evidence_upload_initiate` | Performs the large_evidence_upload_initiate operation against the GoCertius API. Review the API documentation for full field details. |
  | `large_evidence_upload_complete` | Finalize a multipart evidence upload and register the evidence in the group. Returns immediately — the evidence transitions asynchronously to COMPLETED. Poll evidence_list until status is COMPLETED before sealing the group. |

  ## Credentials

  This node requires a "EAD Enterprise Suite API" credential with the following fields:

  | Field | Description | Secret? |
  |---|---|---|
  | `API Base URL` | Base URL of the EAD Enterprise Suite REST API. Production default: `https://api-eadcustody.eadtrust.gocertius.io` Leave blank only if you know your environment uses a different endpoint. | no |
  | `MCP_AUTH_EMAIL` | Your EAD Enterprise Suite account email (Flow 1). Configure one of Flow 1 or Flow 2. | no |
  | `MCP_AUTH_PASSWORD` | Your EAD Enterprise Suite account password (Flow 1, email/password accounts) (See https://www.eadtrust.eu/soluciones-legaltech/enterprise-suite/ for credential acquisition.) | yes |
  > **Need credentials?** Sign up or log in at [https://www.eadtrust.eu/soluciones-legaltech/enterprise-suite/](https://www.eadtrust.eu/soluciones-legaltech/enterprise-suite/).

  ## Use as an AI Agent tool

  This node is flagged `usableAsTool: true`, so any n8n AI Agent (n8n ≥ 1.79.0) can consume it dynamically: drag it into the workflow and wire its main output to an AI Agent's "Tool" input.

  For best results pair with an AI Agent node running **V2** — V3 has a known empty-tool-response bug in some recent n8n versions (see [n8n issue #26202](https://github.com/n8n-io/n8n/issues/26202)).

  ## License

  MIT. See [LICENSE](./LICENSE).

ai_documentation_summary:
  {"purpose":"MCP server connector for EAD Enterprise Suite that exposes workflow operations for managing signatures, evidence, certified notifications, and dossiers inside n8n. It is designed to be used both in normal workflows and with n8n AI Agent-driven automation.","capabilities":["Create, list, retrieve, and seal evidence records and evidence groups","Create, update, list, retrieve, preview, and certify dossiers","List dossier templates and use them when creating dossiers","Support async lifecycle polling for sealing/certification states","Handle file upload flows for evidence via presigned upload URLs","Support evidence creation by direct file URL download or hash-only external registration"],"authentication":"Not mentioned in the README; no explicit auth method is documented.","commonUseCases":["Register evidence files, upload bytes, and certify evidence groups","Aggregate certified evidence into a tamper-evident dossier PDF","Use n8n AI Agent to automate evidence, notification, signature, and dossier workflows"],"limitations":["Evidence sealing and dossier certification are asynchronous and require polling until terminal states are reached","Internal evidence uploads must be completed before sealing an evidence group","Some operations require prior IDs from other steps and UUID v4 values must be generated by the workflow","The README is truncated, so the full operation list may be incomplete"],"relatedNodes":["n8n AI Agent node","HTTP Request node"]}


node_type: n8n-nodes-faceless-video.facelessVideo
package_name: n8n-nodes-faceless-video
display_name: Faceless Video
description: Generate captioned, voiced 9:16 videos via the Faceless Video API
category: Community
development_style: declarative
version: 1
credentials_required: []
outputs:
  [
  "main"
  ]

updated_at: 2026-07-14 14:40:34
author_name: winor30
author_github_url: https://github.com/winor30/
npm_package_name: n8n-nodes-faceless-video
npm_version: 0.1.7
community_fetched_at: 2026-07-14T14:40:34.471Z
ai_summary_generated_at: 2026-06-26 10:29:17
properties_schema:
  [
    {
      "name": "operation",
      "type": "options",
      "default": "generate",
      "options": [
        {
          "name": "Generate",
          "value": "generate",
          "action": "Generate a video",
          "description": "Enqueue a render from a list of segments"
        },
        {
          "name": "Get Result",
          "value": "getResult",
          "action": "Get a video result",
          "description": "Fetch the status and URL of a render job"
        }
      ],
      "displayName": "Operation",
      "noDataExpression": true
    }
  ]

operations:
  [
    {
      "name": "Generate",
      "value": "generate",
      "action": "Generate a video",
      "description": "Enqueue a render from a list of segments"
    },
    {
      "name": "Get Result",
      "value": "getResult",
      "action": "Get a video result",
      "description": "Fetch the status and URL of a render job"
    }
  ]

npm_readme:
  # n8n-nodes-faceless-video

  An [n8n](https://n8n.io) community node for the **Faceless Video API** — turn a script (a
  list of segments) into a captioned, voiced short video (**9:16 / 1:1 / 16:9 MP4**) in one
  node, ready to auto-post from your n8n workflows.

  [Installation](#installation) · [Credentials](#credentials) · [Operations](#operations) ·
  [Compatibility](#compatibility)

  ## Installation

  Follow the [community nodes installation guide](https://docs.n8n.io/integrations/community-nodes/installation/),
  or in the n8n UI: **Settings → Community Nodes → Install** `n8n-nodes-faceless-video`.

  ## Credentials

  **Need an API key?** The API is in free beta — [request a beta key here](https://docs.google.com/forms/d/e/1FAIpQLScYBDJJcQLgNq8m23VjpSDyqENROfkFypYGT_rCec2VuGCYVw/viewform). Keys are manually approved.

  Create a **Faceless Video API** credential:

  - **Base URL** — the hosted beta `https://faceless-video-api.onrender.com` (default), or your own URL if you self-host.
  - **API Key** — the `x-api-key` from your beta approval (or your self-hosted key).

  Use the credential's **Test** button to verify the connection.

  ## Operations

  ### Video → Generate

  Enqueue a render. Add one or more **Segments** (each has **Text** and an optional **Image
  URL**), pick a **Voice** and **Aspect Ratio** (9:16 / 1:1 / 16:9), and optionally set a
  **Callback URL**.

  - **Wait for Completion** (default on): the node polls until the render is `done` and returns
    the final `url`. Turn it off to return immediately with a `job_id` (`status: "queued"`).

  ### Video → Get Result

  Fetch a job by **Job ID**. Returns `{ job_id, status, url?, error? }`
  (`status`: `queued | processing | done | failed`).

  ## Example workflow

  **Script → faceless video.** A Manual Trigger feeds three script segments into the node; with
  **Wait for Completion** on, the node returns the finished MP4 `url`. Paste this into n8n
  (**Workflows → Import from File / clipboard**) and set the **Faceless Video API** credential:

  ```json
  {
    "name": "Script → Faceless Video",
    "nodes": [
      {
        "parameters": {},
        "name": "When clicking 'Execute workflow'",
        "type": "n8n-nodes-base.manualTrigger",
        "typeVersion": 1,
        "position": [240, 320]
      },
      {
        "parameters": {
          "operation": "generate",
          "segments": {
            "segment": [
              { "text": "Did you know honey never spoils?" },
              {
                "text": "Archaeologists found 3000-year-old honey in Egyptian tombs, still edible."
              },
              { "text": "Its low moisture and acidity stop bacteria cold." }
            ]
          },
          "voice": "alloy",
          "aspect": "9:16",
          "waitForCompletion": true
        },
        "name": "Faceless Video",
        "type": "n8n-nodes-faceless-video.facelessVideo",
        "typeVersion": 1,
        "position": [480, 320]
      }
    ],
    "connections": {
      "When clicking 'Execute workflow'": {
        "main": [[{ "node": "Faceless Video", "type": "main", "index": 0 }]]
      }
    }
  }
  ```

  The **Faceless Video** node outputs:

  ```json
  {
    "job_id": "…",
    "status": "done",
    "url": "https://your-app.onrender.com/files/<id>.mp4"
  }
  ```

  Add a download / upload node after it (e.g. HTTP Request, or a YouTube/TikTok node) to
  auto-post the result. To return immediately with a `job_id` instead of waiting, turn off
  **Wait for Completion** and poll later with **Get Result**.

  ## Compatibility

  Tested against n8n's current community-node API (`n8nNodesApiVersion: 1`). Requires a running
  Faceless Video API instance.

  ## Resources

  - Faceless Video API — your self-hosted render service (set its URL as the credential's **Base URL**)
  - [n8n community nodes docs](https://docs.n8n.io/integrations/community-nodes/)

ai_documentation_summary:
  {"purpose":"Creates captioned, voiced short-form videos from a list of script segments using the Faceless Video API. It can either wait for the render to finish and return the MP4 URL, or return a queued job ID for later retrieval.","capabilities":["Generate a video render from one or more script segments","Support segment text input with optional image URLs","Choose a voice for the generated narration","Select aspect ratio output: 9:16, 1:1, or 16:9 MP4","Optionally provide a callback URL","Wait for completion and poll until the job is done","Return a job ID immediately when not waiting","Fetch render results by job ID"],"authentication":"API key required via Faceless Video API credential (x-api-key), with a configurable base URL for the hosted beta or a self-hosted instance.","commonUseCases":["Generate short social media videos from scripts for platforms like TikTok, Reels, or Shorts","Automate video creation in n8n workflows and pass the rendered MP4 to upload or posting nodes","Queue video renders and poll later for completion in asynchronous workflows"],"limitations":["Requires a running Faceless Video API instance","API keys are manually approved during the free beta","Only supports the operations documented in the README: Generate and Get Result"],"relatedNodes":["HTTP Request","YouTube","TikTok"]}


node_type: n8n-nodes-notsy.notsy
package_name: n8n-nodes-notsy
display_name: Notsy
description: Issue Mexican CFDI 4.0 invoices, manage customers and read tax reports
category: Community
development_style: declarative
version: 1
credentials_required: []
outputs:
  [
  "main"
  ]

updated_at: 2026-07-14 14:40:34
author_name: ggch95
author_github_url: https://github.com/HEUSAI/
npm_package_name: n8n-nodes-notsy
npm_version: 0.2.2
community_fetched_at: 2026-07-14T14:40:34.472Z
ai_summary_generated_at: 2026-06-26 10:29:17
properties_schema:
  [
    {
      "name": "operation",
      "type": "options",
      "default": "resolver",
      "options": [
        {
          "name": "Cancel CFDI",
          "value": "cancelar",
          "action": "Cancel an issued invoice",
          "routing": {
            "request": {
              "url": "=/agent/facturas/{{$parameter[\"factura_id\"]}}/cancelar",
              "method": "POST"
            }
          },
          "description": "Cancel an issued CFDI with the SAT (reasons 01-04)"
        },
        {
          "name": "Create Customer",
          "value": "createCliente",
          "action": "Create or update a customer",
          "routing": {
            "request": {
              "url": "/agent/clientes",
              "method": "POST"
            }
          },
          "description": "Create or update a customer and get a reusable customer ID"
        },
        {
          "name": "Find Customers",
          "value": "listClientes",
          "action": "Find saved customers",
          "routing": {
            "request": {
              "url": "/agent/clientes",
              "method": "GET"
            }
          },
          "description": "List or search your saved customers by name or RFC"
        },
        {
          "name": "Find Invoices",
          "value": "listFacturas",
          "action": "Find recent invoices",
          "routing": {
            "request": {
              "url": "/agent/facturas",
              "method": "GET"
            }
          },
          "description": "List your most recent invoices"
        },
        {
          "name": "Get Income Tax Report",
          "value": "reporteIsr",
          "action": "Get the income tax report for legal entities",
          "routing": {
            "request": {
              "url": "/agent/reportes/isr",
              "method": "GET"
            }
          },
          "description": "Provisional ISR payment for Mexican legal entities (personas morales)"
        },
        {
          "name": "Get Invoice Status",
          "value": "getFactura",
          "action": "Get the status of an invoice",
          "routing": {
            "request": {
              "url": "=/agent/facturas/{{$parameter[\"factura_id\"]}}",
              "method": "GET"
            }
          },
          "description": "Get the status and details of one invoice"
        },
        {
          "name": "Get VAT Report",
          "value": "reporteIva",
          "action": "Get the value added tax report for a period",
          "routing": {
            "request": {
              "url": "/agent/reportes/iva",
              "method": "GET"
            }
          },
          "description": "Cash-flow VAT (IVA) report: charged, creditable and due"
        },
        {
          "name": "Issue CFDI",
          "value": "emitir",
          "action": "Issue and stamp a tax invoice",
          "routing": {
            "request": {
              "url": "/agent/facturas",
              "method": "POST"
            }
          },
          "description": "Stamp an official CFDI 4.0 with the Mexican tax authority (SAT)"
        },
        {
          "name": "My Account",
          "value": "whoami",
          "action": "View the API key permissions limits and usage",
          "routing": {
            "request": {
              "url": "/agent/whoami",
              "method": "GET"
            }
          },
          "description": "Return the permissions, limits and usage of the API key"
        },
        {
          "name": "Preview Invoice",
          "value": "preview",
          "action": "Preview an invoice without stamping it",
          "routing": {
            "request": {
              "url": "/agent/facturas/preview",
              "method": "POST"
            }
          },
          "description": "Validate and calculate totals at no cost, before issuing"
        },
        {
          "name": "Resolve SAT Keys",
          "value": "resolver",
          "action": "Resolve SAT catalog keys from a description",
          "routing": {
            "request": {
              "url": "/agent/resolver-claves-sat",
              "method": "POST"
            }
          },
          "description": "Turn a description into clave_prodserv, clave_unidad and more"
        }
      ],
      "displayName": "Operation",
      "noDataExpression": true
    }
  ]

operations:
  [
    {
      "name": "Cancel CFDI",
      "value": "cancelar",
      "action": "Cancel an issued invoice",
      "routing": {
        "request": {
          "url": "=/agent/facturas/{{$parameter[\"factura_id\"]}}/cancelar",
          "method": "POST"
        }
      },
      "description": "Cancel an issued CFDI with the SAT (reasons 01-04)"
    },
    {
      "name": "Create Customer",
      "value": "createCliente",
      "action": "Create or update a customer",
      "routing": {
        "request": {
          "url": "/agent/clientes",
          "method": "POST"
        }
      },
      "description": "Create or update a customer and get a reusable customer ID"
    },
    {
      "name": "Find Customers",
      "value": "listClientes",
      "action": "Find saved customers",
      "routing": {
        "request": {
          "url": "/agent/clientes",
          "method": "GET"
        }
      },
      "description": "List or search your saved customers by name or RFC"
    },
    {
      "name": "Find Invoices",
      "value": "listFacturas",
      "action": "Find recent invoices",
      "routing": {
        "request": {
          "url": "/agent/facturas",
          "method": "GET"
        }
      },
      "description": "List your most recent invoices"
    },
    {
      "name": "Get Income Tax Report",
      "value": "reporteIsr",
      "action": "Get the income tax report for legal entities",
      "routing": {
        "request": {
          "url": "/agent/reportes/isr",
          "method": "GET"
        }
      },
      "description": "Provisional ISR payment for Mexican legal entities (personas morales)"
    },
    {
      "name": "Get Invoice Status",
      "value": "getFactura",
      "action": "Get the status of an invoice",
      "routing": {
        "request": {
          "url": "=/agent/facturas/{{$parameter[\"factura_id\"]}}",
          "method": "GET"
        }
      },
      "description": "Get the status and details of one invoice"
    },
    {
      "name": "Get VAT Report",
      "value": "reporteIva",
      "action": "Get the value added tax report for a period",
      "routing": {
        "request": {
          "url": "/agent/reportes/iva",
          "method": "GET"
        }
      },
      "description": "Cash-flow VAT (IVA) report: charged, creditable and due"
    },
    {
      "name": "Issue CFDI",
      "value": "emitir",
      "action": "Issue and stamp a tax invoice",
      "routing": {
        "request": {
          "url": "/agent/facturas",
          "method": "POST"
        }
      },
      "description": "Stamp an official CFDI 4.0 with the Mexican tax authority (SAT)"
    },
    {
      "name": "My Account",
      "value": "whoami",
      "action": "View the API key permissions limits and usage",
      "routing": {
        "request": {
          "url": "/agent/whoami",
          "method": "GET"
        }
      },
      "description": "Return the permissions, limits and usage of the API key"
    },
    {
      "name": "Preview Invoice",
      "value": "preview",
      "action": "Preview an invoice without stamping it",
      "routing": {
        "request": {
          "url": "/agent/facturas/preview",
          "method": "POST"
        }
      },
      "description": "Validate and calculate totals at no cost, before issuing"
    },
    {
      "name": "Resolve SAT Keys",
      "value": "resolver",
      "action": "Resolve SAT catalog keys from a description",
      "routing": {
        "request": {
          "url": "/agent/resolver-claves-sat",
          "method": "POST"
        }
      },
      "description": "Turn a description into clave_prodserv, clave_unidad and more"
    }
  ]

npm_readme:
  # n8n-nodes-notsy

  This is an n8n community node. It lets you use [Notsy Facturación](https://facturacion.notsy.com.mx)
  in your n8n workflows.

  **Notsy** is a Mexican e-invoicing service: it issues official **CFDI 4.0** invoices and resolves
  **SAT** catalog keys from natural-language descriptions, using your Notsy API key.

  [n8n](https://n8n.io/) is a [fair-code licensed](https://docs.n8n.io/reference/license/) workflow
  automation platform.

  [Installation](#installation)
  [Operations](#operations)
  [Credentials](#credentials)
  [Resources](#resources)

  ## Installation

  Follow the [installation guide](https://docs.n8n.io/integrations/community-nodes/installation/) in
  the n8n community nodes documentation.

  In n8n (self-hosted): **Settings → Community Nodes → Install** → `n8n-nodes-notsy`.

  ## Operations

  - **Resolve SAT Keys** — turn a natural-language description into `clave_prodserv`, `clave_unidad`,
    `uso_cfdi`, and more.
  - **Preview Invoice** — validate and calculate totals without stamping or cost (dry run).
  - **Issue CFDI** — issue and stamp an official CFDI 4.0 with the SAT.
  - **Cancel CFDI** — cancel an issued CFDI with the SAT (reasons 01-04).
  - **Find Invoices** / **Get Invoice Status** — list invoices or read one invoice's status.
  - **Find Customers** / **Create Customer** — search saved customers or upsert one (reusable ID).
  - **Get VAT Report** — cash-flow VAT (IVA) report for a period.
  - **Get Income Tax Report** — provisional ISR for Mexican legal entities (personas morales).
  - **My Account** — view the permissions, limits and usage of your API key.

  ## Credentials

  Create a **Notsy API** credential with your **API key** (format `ntsy_...`), which you generate in
  your business dashboard at https://facturacion.notsy.com.mx (section "Connect your AI agent").

  ## Compatibility

  Tested against n8n 1.x. Requires Node.js 20.15 or later.

  ## Usage

  Notsy can also be used from n8n via its **MCP server** (`https://mcp.notsy.com.mx/mcp`) with the
  *MCP Client Tool* node, using the same API key as the header `Authorization: Bearer ntsy_...`.

  ## Resources

  - [n8n community nodes documentation](https://docs.n8n.io/integrations/community-nodes/)
  - [Notsy developer docs](https://facturacion.notsy.com.mx/developers)
  - [Notsy OpenAPI spec](https://facturacion.notsy.com.mx/openapi.json)

  ## License

  [MIT](LICENSE.md)

ai_documentation_summary:
  {"purpose":"Notsy is a Mexican e-invoicing node for n8n that helps issue and manage CFDI 4.0 invoices, resolve SAT catalog keys, and access tax/account reports through the Notsy Facturación API.","capabilities":["Resolve SAT catalog keys from natural-language descriptions","Preview invoices with validation and total calculation without stamping","Issue and stamp official CFDI 4.0 invoices with the SAT","Cancel issued CFDI invoices with supported cancellation reasons 01-04","Find and retrieve invoice records","Check invoice status","Find customers","Create or upsert customers with reusable IDs","Generate VAT (IVA) reports for a period","Generate income tax (ISR) reports for Mexican legal entities"],"authentication":"API key required via a Notsy API credential (key format: ntsy_...)","commonUseCases":["Automating CFDI 4.0 invoice issuance and stamping in n8n workflows","Managing customer records for repeat invoicing","Generating VAT and income tax reports for accounting workflows","Resolving SAT product, unit, and CFDI usage catalog keys from plain-language input","Checking invoice status or canceling invoices programmatically"],"limitations":["Requires a Notsy API key generated in the Notsy business dashboard","Tested against n8n 1.x only","Requires Node.js 20.15 or later","Invoice cancellation is limited to reasons 01-04"],"relatedNodes":["MCP Client Tool"]}


node_type: @mookielianhd/n8n-nodes-infisical.infisical
package_name: @mookielianhd/n8n-nodes-infisical
display_name: Infisical
description: Manage secrets and related resources in Infisical
category: Community
development_style: declarative
version: 1
credentials_required: []
outputs:
  [
  "main"
  ]

updated_at: 2026-07-14 14:40:34
author_name: mookielian
author_github_url: https://github.com/MookieLian/n8n-nodes-infisical.git
npm_package_name: @mookielianhd/n8n-nodes-infisical
npm_version: 0.1.4
community_fetched_at: 2026-07-14T14:40:34.473Z
ai_summary_generated_at: 2026-06-26 10:29:17
properties_schema:
  [
    {
      "name": "resource",
      "type": "options",
      "default": "secret",
      "options": [
        {
          "name": "Audit Log",
          "value": "auditLog"
        },
        {
          "name": "Dynamic Secret",
          "value": "dynamicSecret"
        },
        {
          "name": "Environment",
          "value": "environment"
        },
        {
          "name": "Folder",
          "value": "folder"
        },
        {
          "name": "Identity",
          "value": "identity"
        },
        {
          "name": "Project",
          "value": "project"
        },
        {
          "name": "Secret",
          "value": "secret"
        },
        {
          "name": "Secret Import",
          "value": "secretImport"
        },
        {
          "name": "Secret Tag",
          "value": "secretTag"
        }
      ],
      "displayName": "Resource",
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Create",
          "value": "create",
          "action": "Create a secret",
          "routing": {
            "request": {
              "url": "=/api/v4/secrets/{{ encodeURIComponent($parameter.key) }}",
              "method": "POST"
            }
          },
          "description": "Create a new secret"
        },
        {
          "name": "Delete",
          "value": "delete",
          "action": "Delete a secret",
          "routing": {
            "request": {
              "url": "=/api/v4/secrets/{{ encodeURIComponent($parameter.key) }}",
              "method": "DELETE"
            }
          },
          "description": "Delete a secret"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get a secret",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "secret"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v4/secrets/{{ encodeURIComponent($parameter.key) }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single secret by name"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many secrets",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "secrets"
                  }
                }
              ]
            },
            "request": {
              "url": "/api/v4/secrets",
              "method": "GET"
            }
          },
          "description": "List secrets in an environment and path"
        },
        {
          "name": "Update",
          "value": "update",
          "action": "Update a secret",
          "routing": {
            "request": {
              "url": "=/api/v4/secrets/{{ encodeURIComponent($parameter.key) }}",
              "method": "PATCH"
            }
          },
          "description": "Update an existing secret"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "secret"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Create",
          "value": "create",
          "action": "Create a folder",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "folder"
                  }
                }
              ]
            },
            "request": {
              "url": "/api/v2/folders",
              "method": "POST"
            }
          },
          "description": "Create a new folder"
        },
        {
          "name": "Delete",
          "value": "delete",
          "action": "Delete a folder",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "folder"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v2/folders/{{ encodeURIComponent($parameter.folderId) }}",
              "method": "DELETE"
            }
          },
          "description": "Delete a folder"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get a folder",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "folder"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v2/folders/{{ $parameter.folderId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single folder by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many folders",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "folders"
                  }
                }
              ]
            },
            "request": {
              "url": "/api/v2/folders",
              "method": "GET"
            }
          },
          "description": "List folders in an environment and path"
        },
        {
          "name": "Update",
          "value": "update",
          "action": "Update a folder",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "folder"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v2/folders/{{ encodeURIComponent($parameter.folderId) }}",
              "method": "PATCH"
            }
          },
          "description": "Update an existing folder"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "folder"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Create",
          "value": "create",
          "action": "Create a project",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "project"
                  }
                }
              ]
            },
            "request": {
              "url": "/api/v1/projects",
              "method": "POST"
            }
          },
          "description": "Create a new project"
        },
        {
          "name": "Delete",
          "value": "delete",
          "action": "Delete a project",
          "routing": {
            "send": {
              "preSend": [
                null
              ]
            },
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "project"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v1/projects/{{ $parameter.projectId }}",
              "method": "DELETE"
            }
          },
          "description": "Delete a project"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get a project",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "project"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v1/projects/{{ $parameter.projectId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single project by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many projects",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "projects"
                  }
                }
              ]
            },
            "request": {
              "url": "/api/v1/projects",
              "method": "GET"
            }
          },
          "description": "List the projects the identity can access"
        },
        {
          "name": "Update",
          "value": "update",
          "action": "Update a project",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "project"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v1/projects/{{ $parameter.projectId }}",
              "method": "PATCH"
            }
          },
          "description": "Update an existing project"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "project"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "create",
      "options": [
        {
          "name": "Create",
          "value": "create",
          "action": "Create an environment",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "environment"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v1/projects/{{ $parameter.projectId }}/environments",
              "method": "POST"
            }
          },
          "description": "Create a new environment in a project"
        },
        {
          "name": "Delete",
          "value": "delete",
          "action": "Delete an environment",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "environment"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v1/projects/{{ $parameter.projectId }}/environments/{{ $parameter.environmentId }}",
              "method": "DELETE"
            }
          },
          "description": "Delete an environment from a project"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get an environment",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "environment"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v1/projects/{{ $parameter.projectId }}/environments/{{ $parameter.environmentId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single environment by ID"
        },
        {
          "name": "Update",
          "value": "update",
          "action": "Update an environment",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "environment"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v1/projects/{{ $parameter.projectId }}/environments/{{ $parameter.environmentId }}",
              "method": "PATCH"
            }
          },
          "description": "Update an existing environment"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "environment"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Create",
          "value": "create",
          "action": "Create a secret tag",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "tag"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v1/projects/{{ $parameter.projectId }}/tags",
              "method": "POST"
            }
          },
          "description": "Create a new secret tag"
        },
        {
          "name": "Delete",
          "value": "delete",
          "action": "Delete a secret tag",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "tag"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v1/projects/{{ $parameter.projectId }}/tags/{{ $parameter.tagId }}",
              "method": "DELETE"
            }
          },
          "description": "Delete a secret tag"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get a secret tag",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "tag"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v1/projects/{{ $parameter.projectId }}/tags/{{ $parameter.tagId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single secret tag by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many secret tags",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "tags"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v1/projects/{{ $parameter.projectId }}/tags",
              "method": "GET"
            }
          },
          "description": "List the secret tags in a project"
        },
        {
          "name": "Update",
          "value": "update",
          "action": "Update a secret tag",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "tag"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v1/projects/{{ $parameter.projectId }}/tags/{{ $parameter.tagId }}",
              "method": "PATCH"
            }
          },
          "description": "Update an existing secret tag"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "secretTag"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Create",
          "value": "create",
          "action": "Create a secret import",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "secretImport"
                  }
                }
              ]
            },
            "request": {
              "url": "/api/v2/secret-imports",
              "method": "POST"
            }
          },
          "description": "Create a new secret import"
        },
        {
          "name": "Delete",
          "value": "delete",
          "action": "Delete a secret import",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "secretImport"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v2/secret-imports/{{ $parameter.importId }}",
              "method": "DELETE"
            }
          },
          "description": "Delete a secret import"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get a secret import",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "secretImport"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v2/secret-imports/{{ $parameter.importId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single secret import by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many secret imports",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "secretImports"
                  }
                }
              ]
            },
            "request": {
              "url": "/api/v2/secret-imports",
              "method": "GET"
            }
          },
          "description": "List secret imports in an environment and path"
        },
        {
          "name": "Update",
          "value": "update",
          "action": "Update a secret import",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "secretImport"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v2/secret-imports/{{ $parameter.importId }}",
              "method": "PATCH"
            }
          },
          "description": "Update an existing secret import"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "secretImport"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Create",
          "value": "create",
          "action": "Create a dynamic secret",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "dynamicSecret"
                  }
                }
              ]
            },
            "request": {
              "url": "/api/v1/dynamic-secrets",
              "method": "POST"
            }
          },
          "description": "Create a new dynamic secret configuration"
        },
        {
          "name": "Delete",
          "value": "delete",
          "action": "Delete a dynamic secret",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "dynamicSecret"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v1/dynamic-secrets/{{ encodeURIComponent($parameter.name) }}",
              "method": "DELETE"
            }
          },
          "description": "Delete a dynamic secret configuration"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get a dynamic secret",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "dynamicSecret"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v1/dynamic-secrets/{{ encodeURIComponent($parameter.name) }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single dynamic secret by name"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many dynamic secrets",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "dynamicSecrets"
                  }
                }
              ]
            },
            "request": {
              "url": "/api/v1/dynamic-secrets",
              "method": "GET"
            }
          },
          "description": "List dynamic secrets in an environment"
        },
        {
          "name": "Update",
          "value": "update",
          "action": "Update a dynamic secret",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "dynamicSecret"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v1/dynamic-secrets/{{ encodeURIComponent($parameter.name) }}",
              "method": "PATCH"
            }
          },
          "description": "Update an existing dynamic secret configuration"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "dynamicSecret"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Create",
          "value": "create",
          "action": "Create an identity",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "identity"
                  }
                }
              ]
            },
            "request": {
              "url": "/api/v1/identities",
              "method": "POST"
            }
          },
          "description": "Create a new machine identity"
        },
        {
          "name": "Delete",
          "value": "delete",
          "action": "Delete an identity",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "identity"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v1/identities/{{ $parameter.identityId }}",
              "method": "DELETE"
            }
          },
          "description": "Delete a machine identity"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get an identity",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "identity"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v1/identities/{{ $parameter.identityId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single machine identity by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many identities",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "identities"
                  }
                }
              ]
            },
            "request": {
              "url": "/api/v1/identities",
              "method": "GET"
            }
          },
          "description": "List machine identities in an organization"
        },
        {
          "name": "Update",
          "value": "update",
          "action": "Update an identity",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "identity"
                  }
                }
              ]
            },
            "request": {
              "url": "=/api/v1/identities/{{ $parameter.identityId }}",
              "method": "PATCH"
            }
          },
          "description": "Update an existing machine identity"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "identity"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many audit logs",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "auditLogs"
                  }
                }
              ]
            },
            "request": {
              "url": "/api/v1/organization/audit-logs",
              "method": "GET"
            }
          },
          "description": "Retrieve organization audit logs"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "auditLog"
          ]
        }
      },
      "noDataExpression": true
    }
  ]

operations:
  [
    {
      "name": "Create",
      "value": "create",
      "action": "Create a secret",
      "routing": {
        "request": {
          "url": "=/api/v4/secrets/{{ encodeURIComponent($parameter.key) }}",
          "method": "POST"
        }
      },
      "description": "Create a new secret",
      "resource": "secret"
    },
    {
      "name": "Delete",
      "value": "delete",
      "action": "Delete a secret",
      "routing": {
        "request": {
          "url": "=/api/v4/secrets/{{ encodeURIComponent($parameter.key) }}",
          "method": "DELETE"
        }
      },
      "description": "Delete a secret",
      "resource": "secret"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a secret",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "secret"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v4/secrets/{{ encodeURIComponent($parameter.key) }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single secret by name",
      "resource": "secret"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many secrets",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "secrets"
              }
            }
          ]
        },
        "request": {
          "url": "/api/v4/secrets",
          "method": "GET"
        }
      },
      "description": "List secrets in an environment and path",
      "resource": "secret"
    },
    {
      "name": "Update",
      "value": "update",
      "action": "Update a secret",
      "routing": {
        "request": {
          "url": "=/api/v4/secrets/{{ encodeURIComponent($parameter.key) }}",
          "method": "PATCH"
        }
      },
      "description": "Update an existing secret",
      "resource": "secret"
    },
    {
      "name": "Create",
      "value": "create",
      "action": "Create a folder",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "folder"
              }
            }
          ]
        },
        "request": {
          "url": "/api/v2/folders",
          "method": "POST"
        }
      },
      "description": "Create a new folder",
      "resource": "folder"
    },
    {
      "name": "Delete",
      "value": "delete",
      "action": "Delete a folder",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "folder"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v2/folders/{{ encodeURIComponent($parameter.folderId) }}",
          "method": "DELETE"
        }
      },
      "description": "Delete a folder",
      "resource": "folder"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a folder",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "folder"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v2/folders/{{ $parameter.folderId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single folder by ID",
      "resource": "folder"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many folders",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "folders"
              }
            }
          ]
        },
        "request": {
          "url": "/api/v2/folders",
          "method": "GET"
        }
      },
      "description": "List folders in an environment and path",
      "resource": "folder"
    },
    {
      "name": "Update",
      "value": "update",
      "action": "Update a folder",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "folder"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v2/folders/{{ encodeURIComponent($parameter.folderId) }}",
          "method": "PATCH"
        }
      },
      "description": "Update an existing folder",
      "resource": "folder"
    },
    {
      "name": "Create",
      "value": "create",
      "action": "Create a project",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "project"
              }
            }
          ]
        },
        "request": {
          "url": "/api/v1/projects",
          "method": "POST"
        }
      },
      "description": "Create a new project",
      "resource": "project"
    },
    {
      "name": "Delete",
      "value": "delete",
      "action": "Delete a project",
      "routing": {
        "send": {
          "preSend": [
            null
          ]
        },
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "project"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v1/projects/{{ $parameter.projectId }}",
          "method": "DELETE"
        }
      },
      "description": "Delete a project",
      "resource": "project"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a project",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "project"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v1/projects/{{ $parameter.projectId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single project by ID",
      "resource": "project"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many projects",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "projects"
              }
            }
          ]
        },
        "request": {
          "url": "/api/v1/projects",
          "method": "GET"
        }
      },
      "description": "List the projects the identity can access",
      "resource": "project"
    },
    {
      "name": "Update",
      "value": "update",
      "action": "Update a project",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "project"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v1/projects/{{ $parameter.projectId }}",
          "method": "PATCH"
        }
      },
      "description": "Update an existing project",
      "resource": "project"
    },
    {
      "name": "Create",
      "value": "create",
      "action": "Create an environment",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "environment"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v1/projects/{{ $parameter.projectId }}/environments",
          "method": "POST"
        }
      },
      "description": "Create a new environment in a project",
      "resource": "environment"
    },
    {
      "name": "Delete",
      "value": "delete",
      "action": "Delete an environment",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "environment"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v1/projects/{{ $parameter.projectId }}/environments/{{ $parameter.environmentId }}",
          "method": "DELETE"
        }
      },
      "description": "Delete an environment from a project",
      "resource": "environment"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get an environment",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "environment"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v1/projects/{{ $parameter.projectId }}/environments/{{ $parameter.environmentId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single environment by ID",
      "resource": "environment"
    },
    {
      "name": "Update",
      "value": "update",
      "action": "Update an environment",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "environment"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v1/projects/{{ $parameter.projectId }}/environments/{{ $parameter.environmentId }}",
          "method": "PATCH"
        }
      },
      "description": "Update an existing environment",
      "resource": "environment"
    },
    {
      "name": "Create",
      "value": "create",
      "action": "Create a secret tag",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "tag"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v1/projects/{{ $parameter.projectId }}/tags",
          "method": "POST"
        }
      },
      "description": "Create a new secret tag",
      "resource": "secretTag"
    },
    {
      "name": "Delete",
      "value": "delete",
      "action": "Delete a secret tag",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "tag"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v1/projects/{{ $parameter.projectId }}/tags/{{ $parameter.tagId }}",
          "method": "DELETE"
        }
      },
      "description": "Delete a secret tag",
      "resource": "secretTag"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a secret tag",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "tag"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v1/projects/{{ $parameter.projectId }}/tags/{{ $parameter.tagId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single secret tag by ID",
      "resource": "secretTag"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many secret tags",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "tags"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v1/projects/{{ $parameter.projectId }}/tags",
          "method": "GET"
        }
      },
      "description": "List the secret tags in a project",
      "resource": "secretTag"
    },
    {
      "name": "Update",
      "value": "update",
      "action": "Update a secret tag",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "tag"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v1/projects/{{ $parameter.projectId }}/tags/{{ $parameter.tagId }}",
          "method": "PATCH"
        }
      },
      "description": "Update an existing secret tag",
      "resource": "secretTag"
    },
    {
      "name": "Create",
      "value": "create",
      "action": "Create a secret import",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "secretImport"
              }
            }
          ]
        },
        "request": {
          "url": "/api/v2/secret-imports",
          "method": "POST"
        }
      },
      "description": "Create a new secret import",
      "resource": "secretImport"
    },
    {
      "name": "Delete",
      "value": "delete",
      "action": "Delete a secret import",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "secretImport"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v2/secret-imports/{{ $parameter.importId }}",
          "method": "DELETE"
        }
      },
      "description": "Delete a secret import",
      "resource": "secretImport"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a secret import",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "secretImport"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v2/secret-imports/{{ $parameter.importId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single secret import by ID",
      "resource": "secretImport"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many secret imports",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "secretImports"
              }
            }
          ]
        },
        "request": {
          "url": "/api/v2/secret-imports",
          "method": "GET"
        }
      },
      "description": "List secret imports in an environment and path",
      "resource": "secretImport"
    },
    {
      "name": "Update",
      "value": "update",
      "action": "Update a secret import",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "secretImport"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v2/secret-imports/{{ $parameter.importId }}",
          "method": "PATCH"
        }
      },
      "description": "Update an existing secret import",
      "resource": "secretImport"
    },
    {
      "name": "Create",
      "value": "create",
      "action": "Create a dynamic secret",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "dynamicSecret"
              }
            }
          ]
        },
        "request": {
          "url": "/api/v1/dynamic-secrets",
          "method": "POST"
        }
      },
      "description": "Create a new dynamic secret configuration",
      "resource": "dynamicSecret"
    },
    {
      "name": "Delete",
      "value": "delete",
      "action": "Delete a dynamic secret",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "dynamicSecret"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v1/dynamic-secrets/{{ encodeURIComponent($parameter.name) }}",
          "method": "DELETE"
        }
      },
      "description": "Delete a dynamic secret configuration",
      "resource": "dynamicSecret"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a dynamic secret",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "dynamicSecret"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v1/dynamic-secrets/{{ encodeURIComponent($parameter.name) }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single dynamic secret by name",
      "resource": "dynamicSecret"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many dynamic secrets",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "dynamicSecrets"
              }
            }
          ]
        },
        "request": {
          "url": "/api/v1/dynamic-secrets",
          "method": "GET"
        }
      },
      "description": "List dynamic secrets in an environment",
      "resource": "dynamicSecret"
    },
    {
      "name": "Update",
      "value": "update",
      "action": "Update a dynamic secret",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "dynamicSecret"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v1/dynamic-secrets/{{ encodeURIComponent($parameter.name) }}",
          "method": "PATCH"
        }
      },
      "description": "Update an existing dynamic secret configuration",
      "resource": "dynamicSecret"
    },
    {
      "name": "Create",
      "value": "create",
      "action": "Create an identity",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "identity"
              }
            }
          ]
        },
        "request": {
          "url": "/api/v1/identities",
          "method": "POST"
        }
      },
      "description": "Create a new machine identity",
      "resource": "identity"
    },
    {
      "name": "Delete",
      "value": "delete",
      "action": "Delete an identity",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "identity"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v1/identities/{{ $parameter.identityId }}",
          "method": "DELETE"
        }
      },
      "description": "Delete a machine identity",
      "resource": "identity"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get an identity",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "identity"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v1/identities/{{ $parameter.identityId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single machine identity by ID",
      "resource": "identity"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many identities",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "identities"
              }
            }
          ]
        },
        "request": {
          "url": "/api/v1/identities",
          "method": "GET"
        }
      },
      "description": "List machine identities in an organization",
      "resource": "identity"
    },
    {
      "name": "Update",
      "value": "update",
      "action": "Update an identity",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "identity"
              }
            }
          ]
        },
        "request": {
          "url": "=/api/v1/identities/{{ $parameter.identityId }}",
          "method": "PATCH"
        }
      },
      "description": "Update an existing machine identity",
      "resource": "identity"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many audit logs",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "auditLogs"
              }
            }
          ]
        },
        "request": {
          "url": "/api/v1/organization/audit-logs",
          "method": "GET"
        }
      },
      "description": "Retrieve organization audit logs",
      "resource": "auditLog"
    }
  ]

npm_readme:
  # n8n-nodes-infisical

  This is an n8n community node. It lets you use [Infisical](https://infisical.com) — the open-source secrets, certificates and access management platform — in your n8n workflows.

  It wraps the Infisical REST API directly (no SDK dependency) and supports managing secrets, folders, projects, environments, secret tags, secret imports, dynamic secrets, machine identities, and audit logs.

  [n8n](https://n8n.io) is a [fair-code licensed](https://docs.n8n.io/reference/license/) workflow automation platform.

  [Installation](#installation)
  [Operations](#operations)
  [Credentials](#credentials)
  [Compatibility](#compatibility)
  [Usage](#usage)
  [Resources](#resources)

  ## Installation

  Follow the [installation guide](https://docs.n8n.io/integrations/community-nodes/installation/) in the n8n community nodes documentation.

  In n8n, go to **Settings > Community Nodes**, select **Install**, and enter:

  ```
  @mookielianhd/n8n-nodes-infisical
  ```

  ## Operations

  | Resource | Operations |
  | --- | --- |
  | **Secret** | Create, Get, Get Many, Update, Delete |
  | **Folder** | Create, Get, Get Many, Update, Delete |
  | **Project** | Create, Get, Get Many, Update, Delete |
  | **Environment** | Create, Get, Update, Delete |
  | **Secret Tag** | Create, Get, Get Many, Update, Delete |
  | **Secret Import** | Create, Get, Get Many, Update, Delete |
  | **Dynamic Secret** | Create, Get, Get Many, Update, Delete |
  | **Identity** | Create, Get, Get Many, Update, Delete |
  | **Audit Log** | Get Many |

  ## Credentials

  This node authenticates with Infisical using **Universal Auth** (a machine identity Client ID and Client Secret). The node exchanges these for a short-lived access token automatically and refreshes it when it expires.

  To set up credentials:

  1. In Infisical, create a **Machine Identity** and attach the **Universal Auth** method to it (Organization Settings → Access Control → Identities). See the [Universal Auth docs](https://infisical.com/docs/documentation/platform/identities/universal-auth).
  2. Add the identity to the project(s) you want to manage and grant it the required roles.
  3. Copy the identity's **Client ID** and create a **Client Secret**.
  4. In n8n, create new **Infisical API** credentials and fill in:
     - **Region** — `US Cloud`, `EU Cloud`, or `Custom / Self-Hosted` (with a **Custom Base URL** for self-hosted instances).
     - **Client ID** and **Client Secret**.
  5. Click **Test** to verify the connection.

  ## Compatibility

  Built and tested against n8n's current declarative node API (`n8nNodesApiVersion: 1`). Requires a recent version of n8n.

  ## Usage

  - Most operations require selecting a **Project** (searchable list or manual ID) and an **Environment** (slug). Dynamic secrets use the project **slug** and environment slug instead.
  - The **Secret → Get Many** operation returns decrypted secret values by default. Use the **View Secret Value** option to disable this. Be mindful of where secret values flow in your workflow.
  - **Dynamic Secret → Create** takes a JSON **Provider** object whose shape depends on the provider type (e.g. `postgres`, `redis`, `aws-iam`). Refer to the Infisical dynamic secrets docs for the exact `inputs`.

  ## Resources

  - [n8n community nodes documentation](https://docs.n8n.io/integrations/community-nodes/)
  - [Infisical API reference](https://infisical.com/docs/api-reference/overview/introduction)
  - [Infisical Universal Auth](https://infisical.com/docs/documentation/platform/identities/universal-auth)

  ## License

  [MIT](LICENSE.md)

ai_documentation_summary:
  {"purpose":"This node integrates Infisical with n8n to manage secrets and related resources directly through the Infisical REST API. It supports workflows for secret management, access control, dynamic secrets, and audit log retrieval.","capabilities":["Create, get, list, update, and delete secrets","Create, get, list, update, and delete folders","Create, get, list, update, and delete projects","Create, get, update, and delete environments","Create, get, list, update, and delete secret tags","Create, get, list, update, and delete secret imports","Create, get, list, update, and delete dynamic secrets","Create, get, list, update, and delete machine identities","Get many audit logs"],"authentication":"Universal Auth using a Machine Identity Client ID and Client Secret; the node exchanges these for a short-lived access token and refreshes it automatically. Supports US Cloud, EU Cloud, and Custom/Self-Hosted regions.","commonUseCases":["Automating secret creation and updates across projects and environments","Managing Infisical projects, folders, and secret metadata from n8n","Retrieving audit logs for compliance or monitoring workflows","Provisioning and managing dynamic secrets for external systems"],"limitations":["Most operations require a selected Project and Environment; dynamic secrets use project slug and environment slug instead","Secret -> Get Many returns decrypted secret values by default unless View Secret Value is disabled","Dynamic Secret -> Create requires a provider-specific JSON object whose shape depends on the provider type"],"relatedNodes":["n8n community nodes"]}


node_type: @appomni/n8n-nodes-agentguard.agentguard
package_name: @appomni/n8n-nodes-agentguard
display_name: AppOmni AgentGuard
description: AppOmni's runtime security solution for n8n workflows that leverage AI agents
category: Community
development_style: declarative
version: 1
properties_schema: []
operations: []
credentials_required: []
outputs:
  [
  "main",
  "main"
  ]

updated_at: 2026-07-14 14:40:34
author_name: agentguard-appomni
author_github_url: https://github.com/appomni/n8n-nodes-agentguard.git
npm_package_name: @appomni/n8n-nodes-agentguard
npm_version: 0.1.2
community_fetched_at: 2026-07-14T14:40:34.475Z
ai_summary_generated_at: 2026-06-26 10:29:17
npm_readme:
  # @appomni/n8n-nodes-agentguard

  AppOmni AgentGuard provides runtime security for n8n workflows that leverage AI agents.

  [n8n](https://n8n.io/) is a [fair-code licensed](https://docs.n8n.io/sustainable-use-license/) workflow automation platform.

  [Installation](#installation)
  [Operations](#operations)
  [Credentials](#credentials)
  [Compatibility](#compatibility)
  [Usage](#usage)
  [Resources](#resources)

  ## Installation

  Follow the [installation guide](https://docs.n8n.io/integrations/community-nodes/installation/) in the n8n community nodes documentation.

  ## Operations

  | Resource | Operation | Description |
  |----------|-----------|-------------|
  | Prompt   | Classify  | Send a prompt to AppOmni for DLP and/or prompt firewall analysis. The node has two outputs (`Allowed`, `Blocked`). |

  ## Credentials

  Create an **AgentGuard API** credential with:

  - **Tenant URL** — the URL of your AppOmni tenant (e.g. `https://example.appomni.com`).
  - **Ingest Token** — your AppOmni-issued ingest token; sent as `X-AppOmni-Ingest-Token`.
  - **Host override** *(optional)* — overrides the `X-Host` header; leave blank unless instructed by AppOmni support.

  ## Compatibility

  Last tested against n8n 2.19.2.

  ## Usage

  Wire the node before any LLM call you want to protect:

  ```
  Trigger → AgentGuard ─┬─ Allowed → LLM call
                                           └─ Blocked → log / alert / refuse
  ```

  The output item carries an `agentguard` object with the verdict, the original prompt, and the full API response, ready for downstream nodes.

  If the AppOmni tenant's policy includes a `user_quarantine` classifier, repeat-offender users can be temporarily locked out after a set number of strikes within a rolling window. For Chat Trigger workflows the node auto-populates **User ID** with the chat session ID, so users are quarantine-eligible by default — note that this scopes quarantine to the conversation, so starting a fresh chat session resets the strike count. For persistent identity across sessions (or for non-chat triggers), populate **User ID**, **Username**, or **User Email** under *Additional Metadata* explicitly — these resolve in that priority order, and any value you set there overrides the chat-session default. When a user is locked, AgentGuard returns `response_action: "block"` with `block_reasons` containing the quarantine reason — same shape as any other block, so the existing **Blocked** output handles it without extra wiring. Quarantine windows, strike counts, and lock duration are configured server-side per tenant; nothing needs to change in the workflow.

  ## Resources

  * [n8n community nodes documentation](https://docs.n8n.io/integrations/#community-nodes)
  * [AppOmni](https://appomni.com)

ai_documentation_summary:
  {"purpose":"AppOmni AgentGuard adds runtime security to n8n workflows that use AI agents by classifying prompts for DLP and prompt-firewall policy enforcement. It routes each prompt to either an Allowed or Blocked output based on AppOmni's verdict.","capabilities":["Classify prompts for DLP and/or prompt firewall analysis","Provide two execution outputs: Allowed and Blocked","Attach an agentguard result object containing the verdict, original prompt, and full API response","Support quarantine-based blocking for repeat-offender users when tenant policy includes user_quarantine","Accept optional additional metadata for user identification such as User ID, Username, or User Email"],"authentication":"AgentGuard API credential required: Tenant URL and AppOmni-issued Ingest Token are required, with an optional Host override.","commonUseCases":["Protecting LLM calls in n8n workflows before they reach the model","Blocking or alerting on unsafe prompts based on AppOmni policy","Quarantining repeat-offender users in chat or other AI-agent workflows","Passing prompt verdicts and metadata to downstream logging or enforcement nodes"],"limitations":["Only one listed operation is supported: Prompt -> Classify","Last tested against n8n 2.19.2","Quarantine behavior is configured server-side in the AppOmni tenant, not in the workflow"],"relatedNodes":["n8n LLM/AI agent nodes","n8n Chat Trigger","n8n logging/alerting nodes"]}


node_type: n8n-nodes-shade.shade
package_name: n8n-nodes-shade
display_name: Shade
description: Interact with your Shade workspace
category: Community
development_style: declarative
version: 1
properties_schema: []
operations: []
credentials_required: []
outputs:
  [
  "main"
  ]

updated_at: 2026-07-14 14:40:34
author_name: jayhass
author_github_url: https://github.com/jhasse-shade/shade-n8n.git
npm_package_name: n8n-nodes-shade
npm_version: 1.0.8
community_fetched_at: 2026-07-14T14:40:34.476Z
ai_summary_generated_at: 2026-06-26 10:29:17
npm_readme:
  # n8n-nodes-shade

  This is an n8n community node. It lets you use Shade in your n8n workflows.

  Shade is an AI-powered cloud storage NAS designed to provide you and your team with a single source of truth for accessing, reviewing, and sharing your files.

  [n8n](https://n8n.io/) is a [fair-code licensed](https://docs.n8n.io/sustainable-use-license/) workflow automation platform.

  [Installation](#installation)
  [Operations](#operations)
  [Credentials](#credentials)
  [Compatibility](#compatibility)
  [Resources](#resources)

  ## Installation

  Follow the [installation guide](https://docs.n8n.io/integrations/community-nodes/installation/) in the n8n community nodes documentation.

  ## Operations

  To date, the Shade n8n Node supports these actions:
  ### Folders
  Create a folder
  Get folder shares
  List a folder
  Share a folder

  ### Assets
  Comment on an asset
  Get an asset
  Get asset comments
  Get asset shares
  Get asset transcription
  Search for an asset
  Share an asset
  Update an asset
  Upload an asset

  ## Usage example: Upload a file to Shade

  This walkthrough shows how to upload a file from your local machine into a Shade drive.

  **Workflow: Local file → Shade**

  1. **Read Binary File node**
     - Set **File Path** to the file you want to upload (e.g. `/home/user/reports/q1.pdf`).
     - This node outputs the file as binary data on the `data` property.

  2. **Shade node — Asset › Upload**
     - **Workspace**: select your workspace from the list (or paste its ID).
     - **Drive**: select the target drive from the list (or paste its ID).
     - **Path**: the folder path inside the drive to upload into, e.g. `/reports`. Leave blank to upload to the drive root. 
     - **File Name**: the name the file should have in Shade, e.g. `q1.pdf`.
     - **Binary Property**: the name of the binary field carrying the file — `data` if you used a Read Binary File node with default settings.

  3. **Run the workflow.** On success the Shade node outputs:
     ```json
     {
       "path": "/drive-abc123/reports/q1.pdf",
       "name": "q1.pdf"
     }
     ```

  The same **Workspace** and **Drive** selector pattern is used across all asset and folder operations.

  ## Credentials

  In order to authenticate with Shade, you will need to provide an API Key which can be found in the setting section once logged in. More in depth info here: https://academy.shade.inc/developers/using-the-api/using-the-api

  ## Compatibility

  This node was tested against version 1.122.5. Minimum version of 1.122.1

  ## Resources

  * [n8n community nodes documentation](https://docs.n8n.io/integrations/#community-nodes)
  * [Shade API](https://academy.shade.inc/developers/using-the-api/using-the-api)

ai_documentation_summary:
  {"purpose":"The Shade node lets you interact with your Shade workspace from n8n. It is used to manage folders and assets in Shade, including upload, search, sharing, commenting, and retrieval.","capabilities":["Create folders","List folders","Get folder shares","Share folders","Upload assets/files","Update assets","Get assets","Search for assets","Comment on assets","Get asset comments"],"authentication":"API key required","commonUseCases":["Uploading local files into a Shade drive","Managing shared folders and asset permissions","Searching, reviewing, and commenting on files in a workspace"],"limitations":["Supports only the operations listed in the README","Tested against n8n version 1.122.5 with a minimum supported version of 1.122.1"],"relatedNodes":[]}


node_type: @mookielianhd/n8n-nodes-hetzner-cloud.hetznerCloud
package_name: @mookielianhd/n8n-nodes-hetzner-cloud
display_name: Hetzner Cloud
description: Manage servers, volumes, networks and more in Hetzner Cloud
category: Community
development_style: declarative
version: 1
credentials_required: []
outputs:
  [
  "main"
  ]

updated_at: 2026-07-14 14:40:34
author_name: mookielian
author_github_url: https://github.com/MookieLian/n8n-nodes-hetzner-cloud.git
npm_package_name: @mookielianhd/n8n-nodes-hetzner-cloud
npm_version: 0.1.2
community_fetched_at: 2026-07-14T14:40:34.476Z
ai_summary_generated_at: 2026-06-26 10:29:17
properties_schema:
  [
    {
      "name": "resource",
      "type": "options",
      "default": "server",
      "options": [
        {
          "name": "Action",
          "value": "action"
        },
        {
          "name": "Certificate",
          "value": "certificate"
        },
        {
          "name": "Datacenter",
          "value": "datacenter"
        },
        {
          "name": "Firewall",
          "value": "firewall"
        },
        {
          "name": "Floating IP",
          "value": "floatingIp"
        },
        {
          "name": "Image",
          "value": "image"
        },
        {
          "name": "ISO",
          "value": "iso"
        },
        {
          "name": "Load Balancer",
          "value": "loadBalancer"
        },
        {
          "name": "Load Balancer Type",
          "value": "loadBalancerType"
        },
        {
          "name": "Location",
          "value": "location"
        },
        {
          "name": "Network",
          "value": "network"
        },
        {
          "name": "Placement Group",
          "value": "placementGroup"
        },
        {
          "name": "Pricing",
          "value": "pricing"
        },
        {
          "name": "Primary IP",
          "value": "primaryIp"
        },
        {
          "name": "Server",
          "value": "server"
        },
        {
          "name": "Server Type",
          "value": "serverType"
        },
        {
          "name": "SSH Key",
          "value": "sshKey"
        },
        {
          "name": "Volume",
          "value": "volume"
        }
      ],
      "displayName": "Resource",
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Attach ISO",
          "value": "attachIso",
          "action": "Attach an ISO to a server",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/servers/{{ $parameter.serverId }}/actions/attach_iso",
              "method": "POST"
            }
          },
          "description": "Attach an ISO to a server"
        },
        {
          "name": "Change Protection",
          "value": "changeProtection",
          "action": "Change server protection",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/servers/{{ $parameter.serverId }}/actions/change_protection",
              "method": "POST"
            }
          },
          "description": "Change the delete and rebuild protection of a server"
        },
        {
          "name": "Change Type",
          "value": "changeType",
          "action": "Change the server type",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/servers/{{ $parameter.serverId }}/actions/change_type",
              "method": "POST"
            }
          },
          "description": "Change the type (size) of a server"
        },
        {
          "name": "Create",
          "value": "create",
          "action": "Create a server",
          "routing": {
            "send": {
              "preSend": [
                null,
                null
              ]
            },
            "request": {
              "url": "/v1/servers",
              "method": "POST"
            }
          },
          "description": "Create a new server"
        },
        {
          "name": "Create Image",
          "value": "createImage",
          "action": "Create an image from a server",
          "routing": {
            "request": {
              "url": "=/v1/servers/{{ $parameter.serverId }}/actions/create_image",
              "method": "POST"
            }
          },
          "description": "Create an image (snapshot or backup) from a server"
        },
        {
          "name": "Delete",
          "value": "delete",
          "action": "Delete a server",
          "routing": {
            "request": {
              "url": "=/v1/servers/{{ $parameter.serverId }}",
              "method": "DELETE"
            }
          },
          "description": "Delete a server"
        },
        {
          "name": "Detach ISO",
          "value": "detachIso",
          "action": "Detach an ISO from a server",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/servers/{{ $parameter.serverId }}/actions/detach_iso",
              "method": "POST"
            }
          },
          "description": "Detach the attached ISO from a server"
        },
        {
          "name": "Disable Rescue",
          "value": "disableRescue",
          "action": "Disable rescue mode",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/servers/{{ $parameter.serverId }}/actions/disable_rescue",
              "method": "POST"
            }
          },
          "description": "Disable rescue mode for a server"
        },
        {
          "name": "Enable Rescue",
          "value": "enableRescue",
          "action": "Enable rescue mode",
          "routing": {
            "request": {
              "url": "=/v1/servers/{{ $parameter.serverId }}/actions/enable_rescue",
              "method": "POST"
            }
          },
          "description": "Enable rescue mode for a server (returns a root password)"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get a server",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "server"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/servers/{{ $parameter.serverId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single server by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many servers",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "servers"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/servers",
              "method": "GET"
            }
          },
          "description": "List servers in the project"
        },
        {
          "name": "Power Off",
          "value": "powerOff",
          "action": "Power off a server",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/servers/{{ $parameter.serverId }}/actions/poweroff",
              "method": "POST"
            }
          },
          "description": "Cut power to a server (hard power off)"
        },
        {
          "name": "Power On",
          "value": "powerOn",
          "action": "Power on a server",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/servers/{{ $parameter.serverId }}/actions/poweron",
              "method": "POST"
            }
          },
          "description": "Power on a server"
        },
        {
          "name": "Reboot",
          "value": "reboot",
          "action": "Reboot a server",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/servers/{{ $parameter.serverId }}/actions/reboot",
              "method": "POST"
            }
          },
          "description": "Soft-reboot a server (ACPI)"
        },
        {
          "name": "Rebuild",
          "value": "rebuild",
          "action": "Rebuild a server from an image",
          "routing": {
            "request": {
              "url": "=/v1/servers/{{ $parameter.serverId }}/actions/rebuild",
              "method": "POST"
            }
          },
          "description": "Rebuild a server from an image (returns a root password)"
        },
        {
          "name": "Reset",
          "value": "reset",
          "action": "Reset a server",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/servers/{{ $parameter.serverId }}/actions/reset",
              "method": "POST"
            }
          },
          "description": "Cut power to and restart a server (hard reset)"
        },
        {
          "name": "Reset Password",
          "value": "resetPassword",
          "action": "Reset the root password",
          "routing": {
            "request": {
              "url": "=/v1/servers/{{ $parameter.serverId }}/actions/reset_password",
              "method": "POST"
            }
          },
          "description": "Reset the root password of a server (returns a new root password)"
        },
        {
          "name": "Shutdown",
          "value": "shutdown",
          "action": "Shut down a server",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/servers/{{ $parameter.serverId }}/actions/shutdown",
              "method": "POST"
            }
          },
          "description": "Send an ACPI shutdown request to a server"
        },
        {
          "name": "Update",
          "value": "update",
          "action": "Update a server",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "server"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/servers/{{ $parameter.serverId }}",
              "method": "PUT"
            }
          },
          "description": "Update an existing server (name and labels)"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "server"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Create",
          "value": "create",
          "action": "Create an SSH key",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "ssh_key"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/ssh_keys",
              "method": "POST"
            }
          },
          "description": "Add a new SSH key to the project"
        },
        {
          "name": "Delete",
          "value": "delete",
          "action": "Delete an SSH key",
          "routing": {
            "request": {
              "url": "=/v1/ssh_keys/{{ $parameter.sshKeyId }}",
              "method": "DELETE"
            }
          },
          "description": "Delete an SSH key"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get an SSH key",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "ssh_key"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/ssh_keys/{{ $parameter.sshKeyId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single SSH key by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many SSH keys",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "ssh_keys"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/ssh_keys",
              "method": "GET"
            }
          },
          "description": "List SSH keys in the project"
        },
        {
          "name": "Update",
          "value": "update",
          "action": "Update an SSH key",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "ssh_key"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/ssh_keys/{{ $parameter.sshKeyId }}",
              "method": "PUT"
            }
          },
          "description": "Update an existing SSH key (name and labels)"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "sshKey"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Attach",
          "value": "attach",
          "action": "Attach a volume to a server",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/volumes/{{ $parameter.volumeId }}/actions/attach",
              "method": "POST"
            }
          },
          "description": "Attach a volume to a server"
        },
        {
          "name": "Change Protection",
          "value": "changeProtection",
          "action": "Change volume protection",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/volumes/{{ $parameter.volumeId }}/actions/change_protection",
              "method": "POST"
            }
          },
          "description": "Change the delete protection of a volume"
        },
        {
          "name": "Create",
          "value": "create",
          "action": "Create a volume",
          "routing": {
            "request": {
              "url": "/v1/volumes",
              "method": "POST"
            }
          },
          "description": "Create a new volume"
        },
        {
          "name": "Delete",
          "value": "delete",
          "action": "Delete a volume",
          "routing": {
            "request": {
              "url": "=/v1/volumes/{{ $parameter.volumeId }}",
              "method": "DELETE"
            }
          },
          "description": "Delete a volume"
        },
        {
          "name": "Detach",
          "value": "detach",
          "action": "Detach a volume from its server",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/volumes/{{ $parameter.volumeId }}/actions/detach",
              "method": "POST"
            }
          },
          "description": "Detach a volume from the server it is attached to"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get a volume",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "volume"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/volumes/{{ $parameter.volumeId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single volume by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many volumes",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "volumes"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/volumes",
              "method": "GET"
            }
          },
          "description": "List volumes in the project"
        },
        {
          "name": "Resize",
          "value": "resize",
          "action": "Resize a volume",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/volumes/{{ $parameter.volumeId }}/actions/resize",
              "method": "POST"
            }
          },
          "description": "Increase the size of a volume"
        },
        {
          "name": "Update",
          "value": "update",
          "action": "Update a volume",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "volume"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/volumes/{{ $parameter.volumeId }}",
              "method": "PUT"
            }
          },
          "description": "Update an existing volume (name and labels)"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "volume"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Add Route",
          "value": "addRoute",
          "action": "Add a route to a network",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/networks/{{ $parameter.networkId }}/actions/add_route",
              "method": "POST"
            }
          },
          "description": "Add a route to a network"
        },
        {
          "name": "Add Subnet",
          "value": "addSubnet",
          "action": "Add a subnet to a network",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/networks/{{ $parameter.networkId }}/actions/add_subnet",
              "method": "POST"
            }
          },
          "description": "Add a subnet to a network"
        },
        {
          "name": "Change IP Range",
          "value": "changeIpRange",
          "action": "Change the IP range of a network",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/networks/{{ $parameter.networkId }}/actions/change_ip_range",
              "method": "POST"
            }
          },
          "description": "Change the IP range of a network"
        },
        {
          "name": "Change Protection",
          "value": "changeProtection",
          "action": "Change network protection",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/networks/{{ $parameter.networkId }}/actions/change_protection",
              "method": "POST"
            }
          },
          "description": "Change the delete protection of a network"
        },
        {
          "name": "Create",
          "value": "create",
          "action": "Create a network",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "network"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/networks",
              "method": "POST"
            }
          },
          "description": "Create a new network"
        },
        {
          "name": "Delete",
          "value": "delete",
          "action": "Delete a network",
          "routing": {
            "request": {
              "url": "=/v1/networks/{{ $parameter.networkId }}",
              "method": "DELETE"
            }
          },
          "description": "Delete a network"
        },
        {
          "name": "Delete Route",
          "value": "deleteRoute",
          "action": "Delete a route from a network",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/networks/{{ $parameter.networkId }}/actions/del_route",
              "method": "POST"
            }
          },
          "description": "Delete a route from a network"
        },
        {
          "name": "Delete Subnet",
          "value": "deleteSubnet",
          "action": "Delete a subnet from a network",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/networks/{{ $parameter.networkId }}/actions/del_subnet",
              "method": "POST"
            }
          },
          "description": "Delete a subnet from a network"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get a network",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "network"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/networks/{{ $parameter.networkId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single network by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many networks",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "networks"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/networks",
              "method": "GET"
            }
          },
          "description": "List networks in the project"
        },
        {
          "name": "Update",
          "value": "update",
          "action": "Update a network",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "network"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/networks/{{ $parameter.networkId }}",
              "method": "PUT"
            }
          },
          "description": "Update an existing network (name and labels)"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "network"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Apply to Resources",
          "value": "applyToResources",
          "action": "Apply a firewall to resources",
          "routing": {
            "send": {
              "preSend": [
                null
              ]
            },
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "actions"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/firewalls/{{ $parameter.firewallId }}/actions/apply_to_resources",
              "method": "POST"
            }
          },
          "description": "Apply the firewall to servers or label selectors"
        },
        {
          "name": "Create",
          "value": "create",
          "action": "Create a firewall",
          "routing": {
            "send": {
              "preSend": [
                null,
                null
              ]
            },
            "request": {
              "url": "/v1/firewalls",
              "method": "POST"
            }
          },
          "description": "Create a new firewall"
        },
        {
          "name": "Delete",
          "value": "delete",
          "action": "Delete a firewall",
          "routing": {
            "request": {
              "url": "=/v1/firewalls/{{ $parameter.firewallId }}",
              "method": "DELETE"
            }
          },
          "description": "Delete a firewall"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get a firewall",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "firewall"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/firewalls/{{ $parameter.firewallId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single firewall by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many firewalls",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "firewalls"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/firewalls",
              "method": "GET"
            }
          },
          "description": "List firewalls in the project"
        },
        {
          "name": "Remove From Resources",
          "value": "removeFromResources",
          "action": "Remove a firewall from resources",
          "routing": {
            "send": {
              "preSend": [
                null
              ]
            },
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "actions"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/firewalls/{{ $parameter.firewallId }}/actions/remove_from_resources",
              "method": "POST"
            }
          },
          "description": "Remove the firewall from servers or label selectors"
        },
        {
          "name": "Set Rules",
          "value": "setRules",
          "action": "Set firewall rules",
          "routing": {
            "send": {
              "preSend": [
                null
              ]
            },
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "actions"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/firewalls/{{ $parameter.firewallId }}/actions/set_rules",
              "method": "POST"
            }
          },
          "description": "Replace all rules of a firewall"
        },
        {
          "name": "Update",
          "value": "update",
          "action": "Update a firewall",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "firewall"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/firewalls/{{ $parameter.firewallId }}",
              "method": "PUT"
            }
          },
          "description": "Update an existing firewall (name and labels)"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "firewall"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Add Service",
          "value": "addService",
          "action": "Add a service to a load balancer",
          "routing": {
            "send": {
              "preSend": [
                null
              ]
            },
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/load_balancers/{{ $parameter.loadBalancerId }}/actions/add_service",
              "method": "POST"
            }
          },
          "description": "Add a service to a load balancer"
        },
        {
          "name": "Add Target",
          "value": "addTarget",
          "action": "Add a target to a load balancer",
          "routing": {
            "send": {
              "preSend": [
                null
              ]
            },
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/load_balancers/{{ $parameter.loadBalancerId }}/actions/add_target",
              "method": "POST"
            }
          },
          "description": "Add a target to a load balancer"
        },
        {
          "name": "Change Algorithm",
          "value": "changeAlgorithm",
          "action": "Change the load balancer algorithm",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/load_balancers/{{ $parameter.loadBalancerId }}/actions/change_algorithm",
              "method": "POST"
            }
          },
          "description": "Change the algorithm of a load balancer"
        },
        {
          "name": "Change Protection",
          "value": "changeProtection",
          "action": "Change load balancer protection",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/load_balancers/{{ $parameter.loadBalancerId }}/actions/change_protection",
              "method": "POST"
            }
          },
          "description": "Change the delete protection of a load balancer"
        },
        {
          "name": "Change Type",
          "value": "changeType",
          "action": "Change the load balancer type",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/load_balancers/{{ $parameter.loadBalancerId }}/actions/change_type",
              "method": "POST"
            }
          },
          "description": "Change the type of a load balancer"
        },
        {
          "name": "Create",
          "value": "create",
          "action": "Create a load balancer",
          "routing": {
            "request": {
              "url": "/v1/load_balancers",
              "method": "POST"
            }
          },
          "description": "Create a new load balancer"
        },
        {
          "name": "Delete",
          "value": "delete",
          "action": "Delete a load balancer",
          "routing": {
            "request": {
              "url": "=/v1/load_balancers/{{ $parameter.loadBalancerId }}",
              "method": "DELETE"
            }
          },
          "description": "Delete a load balancer"
        },
        {
          "name": "Delete Service",
          "value": "deleteService",
          "action": "Delete a service from a load balancer",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/load_balancers/{{ $parameter.loadBalancerId }}/actions/delete_service",
              "method": "POST"
            }
          },
          "description": "Delete a service from a load balancer"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get a load balancer",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "load_balancer"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/load_balancers/{{ $parameter.loadBalancerId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single load balancer by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many load balancers",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "load_balancers"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/load_balancers",
              "method": "GET"
            }
          },
          "description": "List load balancers in the project"
        },
        {
          "name": "Remove Target",
          "value": "removeTarget",
          "action": "Remove a target from a load balancer",
          "routing": {
            "send": {
              "preSend": [
                null
              ]
            },
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/load_balancers/{{ $parameter.loadBalancerId }}/actions/remove_target",
              "method": "POST"
            }
          },
          "description": "Remove a target from a load balancer"
        },
        {
          "name": "Update",
          "value": "update",
          "action": "Update a load balancer",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "load_balancer"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/load_balancers/{{ $parameter.loadBalancerId }}",
              "method": "PUT"
            }
          },
          "description": "Update an existing load balancer (name and labels)"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "loadBalancer"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Assign",
          "value": "assign",
          "action": "Assign a floating ip to a server",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/floating_ips/{{ $parameter.floatingIpId }}/actions/assign",
              "method": "POST"
            }
          },
          "description": "Assign a Floating IP to a server"
        },
        {
          "name": "Change DNS PTR",
          "value": "changeDnsPtr",
          "action": "Change the reverse dns of a floating ip",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/floating_ips/{{ $parameter.floatingIpId }}/actions/change_dns_ptr",
              "method": "POST"
            }
          },
          "description": "Change the reverse DNS (PTR) entry of a Floating IP"
        },
        {
          "name": "Change Protection",
          "value": "changeProtection",
          "action": "Change floating ip protection",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/floating_ips/{{ $parameter.floatingIpId }}/actions/change_protection",
              "method": "POST"
            }
          },
          "description": "Change the delete protection of a Floating IP"
        },
        {
          "name": "Create",
          "value": "create",
          "action": "Create a floating ip",
          "routing": {
            "request": {
              "url": "/v1/floating_ips",
              "method": "POST"
            }
          },
          "description": "Create a new Floating IP"
        },
        {
          "name": "Delete",
          "value": "delete",
          "action": "Delete a floating ip",
          "routing": {
            "request": {
              "url": "=/v1/floating_ips/{{ $parameter.floatingIpId }}",
              "method": "DELETE"
            }
          },
          "description": "Delete a Floating IP"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get a floating ip",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "floating_ip"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/floating_ips/{{ $parameter.floatingIpId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single Floating IP by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many floating ips",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "floating_ips"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/floating_ips",
              "method": "GET"
            }
          },
          "description": "List Floating IPs in the project"
        },
        {
          "name": "Unassign",
          "value": "unassign",
          "action": "Unassign a floating ip",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/floating_ips/{{ $parameter.floatingIpId }}/actions/unassign",
              "method": "POST"
            }
          },
          "description": "Unassign a Floating IP from its server"
        },
        {
          "name": "Update",
          "value": "update",
          "action": "Update a floating ip",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "floating_ip"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/floating_ips/{{ $parameter.floatingIpId }}",
              "method": "PUT"
            }
          },
          "description": "Update an existing Floating IP (name, description, labels)"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "floatingIp"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Assign",
          "value": "assign",
          "action": "Assign a primary ip to a server",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/primary_ips/{{ $parameter.primaryIpId }}/actions/assign",
              "method": "POST"
            }
          },
          "description": "Assign a Primary IP to a server"
        },
        {
          "name": "Change DNS PTR",
          "value": "changeDnsPtr",
          "action": "Change the reverse dns of a primary ip",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/primary_ips/{{ $parameter.primaryIpId }}/actions/change_dns_ptr",
              "method": "POST"
            }
          },
          "description": "Change the reverse DNS (PTR) entry of a Primary IP"
        },
        {
          "name": "Change Protection",
          "value": "changeProtection",
          "action": "Change primary ip protection",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/primary_ips/{{ $parameter.primaryIpId }}/actions/change_protection",
              "method": "POST"
            }
          },
          "description": "Change the delete protection of a Primary IP"
        },
        {
          "name": "Create",
          "value": "create",
          "action": "Create a primary ip",
          "routing": {
            "request": {
              "url": "/v1/primary_ips",
              "method": "POST"
            }
          },
          "description": "Create a new Primary IP"
        },
        {
          "name": "Delete",
          "value": "delete",
          "action": "Delete a primary ip",
          "routing": {
            "request": {
              "url": "=/v1/primary_ips/{{ $parameter.primaryIpId }}",
              "method": "DELETE"
            }
          },
          "description": "Delete a Primary IP"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get a primary ip",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "primary_ip"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/primary_ips/{{ $parameter.primaryIpId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single Primary IP by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many primary ips",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "primary_ips"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/primary_ips",
              "method": "GET"
            }
          },
          "description": "List Primary IPs in the project"
        },
        {
          "name": "Unassign",
          "value": "unassign",
          "action": "Unassign a primary ip",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/primary_ips/{{ $parameter.primaryIpId }}/actions/unassign",
              "method": "POST"
            }
          },
          "description": "Unassign a Primary IP from its server"
        },
        {
          "name": "Update",
          "value": "update",
          "action": "Update a primary ip",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "primary_ip"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/primary_ips/{{ $parameter.primaryIpId }}",
              "method": "PUT"
            }
          },
          "description": "Update an existing Primary IP (name, labels, auto-delete)"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "primaryIp"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Create",
          "value": "create",
          "action": "Create a certificate",
          "routing": {
            "request": {
              "url": "/v1/certificates",
              "method": "POST"
            }
          },
          "description": "Upload or request a managed certificate"
        },
        {
          "name": "Delete",
          "value": "delete",
          "action": "Delete a certificate",
          "routing": {
            "request": {
              "url": "=/v1/certificates/{{ $parameter.certificateId }}",
              "method": "DELETE"
            }
          },
          "description": "Delete a certificate"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get a certificate",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "certificate"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/certificates/{{ $parameter.certificateId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single certificate by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many certificates",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "certificates"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/certificates",
              "method": "GET"
            }
          },
          "description": "List certificates in the project"
        },
        {
          "name": "Retry",
          "value": "retry",
          "action": "Retry a managed certificate",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/certificates/{{ $parameter.certificateId }}/actions/retry",
              "method": "POST"
            }
          },
          "description": "Retry issuance of a failed managed certificate"
        },
        {
          "name": "Update",
          "value": "update",
          "action": "Update a certificate",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "certificate"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/certificates/{{ $parameter.certificateId }}",
              "method": "PUT"
            }
          },
          "description": "Update an existing certificate (name and labels)"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "certificate"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Change Protection",
          "value": "changeProtection",
          "action": "Change image protection",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/images/{{ $parameter.imageId }}/actions/change_protection",
              "method": "POST"
            }
          },
          "description": "Change the delete protection of an image"
        },
        {
          "name": "Delete",
          "value": "delete",
          "action": "Delete an image",
          "routing": {
            "request": {
              "url": "=/v1/images/{{ $parameter.imageId }}",
              "method": "DELETE"
            }
          },
          "description": "Delete an image (snapshot or backup)"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get an image",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "image"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/images/{{ $parameter.imageId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single image by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many images",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "images"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/images",
              "method": "GET"
            }
          },
          "description": "List images available to the project"
        },
        {
          "name": "Update",
          "value": "update",
          "action": "Update an image",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "image"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/images/{{ $parameter.imageId }}",
              "method": "PUT"
            }
          },
          "description": "Update an existing image (description, type, labels)"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "image"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Create",
          "value": "create",
          "action": "Create a placement group",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "placement_group"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/placement_groups",
              "method": "POST"
            }
          },
          "description": "Create a new placement group"
        },
        {
          "name": "Delete",
          "value": "delete",
          "action": "Delete a placement group",
          "routing": {
            "request": {
              "url": "=/v1/placement_groups/{{ $parameter.placementGroupId }}",
              "method": "DELETE"
            }
          },
          "description": "Delete a placement group"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get a placement group",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "placement_group"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/placement_groups/{{ $parameter.placementGroupId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single placement group by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many placement groups",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "placement_groups"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/placement_groups",
              "method": "GET"
            }
          },
          "description": "List placement groups in the project"
        },
        {
          "name": "Update",
          "value": "update",
          "action": "Update a placement group",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "placement_group"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/placement_groups/{{ $parameter.placementGroupId }}",
              "method": "PUT"
            }
          },
          "description": "Update an existing placement group (name and labels)"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "placementGroup"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Get",
          "value": "get",
          "action": "Get a server type",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "server_type"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/server_types/{{ $parameter.serverTypeId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single server type by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many server types",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "server_types"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/server_types",
              "method": "GET"
            }
          },
          "description": "List the available server types"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "serverType"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Get",
          "value": "get",
          "action": "Get a load balancer type",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "load_balancer_type"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/load_balancer_types/{{ $parameter.loadBalancerTypeId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single load balancer type by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many load balancer types",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "load_balancer_types"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/load_balancer_types",
              "method": "GET"
            }
          },
          "description": "List the available load balancer types"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "loadBalancerType"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Get",
          "value": "get",
          "action": "Get a datacenter",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "datacenter"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/datacenters/{{ $parameter.datacenterId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single datacenter by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many datacenters",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "datacenters"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/datacenters",
              "method": "GET"
            }
          },
          "description": "List the available datacenters"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "datacenter"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Get",
          "value": "get",
          "action": "Get a location",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "location"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/locations/{{ $parameter.locationId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single location by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many locations",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "locations"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/locations",
              "method": "GET"
            }
          },
          "description": "List the available locations"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "location"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Get",
          "value": "get",
          "action": "Get an ISO",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "iso"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/isos/{{ $parameter.isoId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single ISO by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many isos",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "isos"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/isos",
              "method": "GET"
            }
          },
          "description": "List the available ISOs"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "iso"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Get",
          "value": "get",
          "action": "Get an action",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "action"
                  }
                }
              ]
            },
            "request": {
              "url": "=/v1/actions/{{ $parameter.actionId }}",
              "method": "GET"
            }
          },
          "description": "Retrieve a single action by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many actions",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "actions"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/actions",
              "method": "GET"
            }
          },
          "description": "List actions across many resources"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "action"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "get",
      "options": [
        {
          "name": "Get",
          "value": "get",
          "action": "Get pricing",
          "routing": {
            "output": {
              "postReceive": [
                {
                  "type": "rootProperty",
                  "properties": {
                    "property": "pricing"
                  }
                }
              ]
            },
            "request": {
              "url": "/v1/pricing",
              "method": "GET"
            }
          },
          "description": "Retrieve current prices for all resources"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "pricing"
          ]
        }
      },
      "noDataExpression": true
    }
  ]

operations:
  [
    {
      "name": "Attach ISO",
      "value": "attachIso",
      "action": "Attach an ISO to a server",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/servers/{{ $parameter.serverId }}/actions/attach_iso",
          "method": "POST"
        }
      },
      "description": "Attach an ISO to a server",
      "resource": "server"
    },
    {
      "name": "Change Protection",
      "value": "changeProtection",
      "action": "Change server protection",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/servers/{{ $parameter.serverId }}/actions/change_protection",
          "method": "POST"
        }
      },
      "description": "Change the delete and rebuild protection of a server",
      "resource": "server"
    },
    {
      "name": "Change Type",
      "value": "changeType",
      "action": "Change the server type",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/servers/{{ $parameter.serverId }}/actions/change_type",
          "method": "POST"
        }
      },
      "description": "Change the type (size) of a server",
      "resource": "server"
    },
    {
      "name": "Create",
      "value": "create",
      "action": "Create a server",
      "routing": {
        "send": {
          "preSend": [
            null,
            null
          ]
        },
        "request": {
          "url": "/v1/servers",
          "method": "POST"
        }
      },
      "description": "Create a new server",
      "resource": "server"
    },
    {
      "name": "Create Image",
      "value": "createImage",
      "action": "Create an image from a server",
      "routing": {
        "request": {
          "url": "=/v1/servers/{{ $parameter.serverId }}/actions/create_image",
          "method": "POST"
        }
      },
      "description": "Create an image (snapshot or backup) from a server",
      "resource": "server"
    },
    {
      "name": "Delete",
      "value": "delete",
      "action": "Delete a server",
      "routing": {
        "request": {
          "url": "=/v1/servers/{{ $parameter.serverId }}",
          "method": "DELETE"
        }
      },
      "description": "Delete a server",
      "resource": "server"
    },
    {
      "name": "Detach ISO",
      "value": "detachIso",
      "action": "Detach an ISO from a server",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/servers/{{ $parameter.serverId }}/actions/detach_iso",
          "method": "POST"
        }
      },
      "description": "Detach the attached ISO from a server",
      "resource": "server"
    },
    {
      "name": "Disable Rescue",
      "value": "disableRescue",
      "action": "Disable rescue mode",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/servers/{{ $parameter.serverId }}/actions/disable_rescue",
          "method": "POST"
        }
      },
      "description": "Disable rescue mode for a server",
      "resource": "server"
    },
    {
      "name": "Enable Rescue",
      "value": "enableRescue",
      "action": "Enable rescue mode",
      "routing": {
        "request": {
          "url": "=/v1/servers/{{ $parameter.serverId }}/actions/enable_rescue",
          "method": "POST"
        }
      },
      "description": "Enable rescue mode for a server (returns a root password)",
      "resource": "server"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a server",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "server"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/servers/{{ $parameter.serverId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single server by ID",
      "resource": "server"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many servers",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "servers"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/servers",
          "method": "GET"
        }
      },
      "description": "List servers in the project",
      "resource": "server"
    },
    {
      "name": "Power Off",
      "value": "powerOff",
      "action": "Power off a server",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/servers/{{ $parameter.serverId }}/actions/poweroff",
          "method": "POST"
        }
      },
      "description": "Cut power to a server (hard power off)",
      "resource": "server"
    },
    {
      "name": "Power On",
      "value": "powerOn",
      "action": "Power on a server",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/servers/{{ $parameter.serverId }}/actions/poweron",
          "method": "POST"
        }
      },
      "description": "Power on a server",
      "resource": "server"
    },
    {
      "name": "Reboot",
      "value": "reboot",
      "action": "Reboot a server",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/servers/{{ $parameter.serverId }}/actions/reboot",
          "method": "POST"
        }
      },
      "description": "Soft-reboot a server (ACPI)",
      "resource": "server"
    },
    {
      "name": "Rebuild",
      "value": "rebuild",
      "action": "Rebuild a server from an image",
      "routing": {
        "request": {
          "url": "=/v1/servers/{{ $parameter.serverId }}/actions/rebuild",
          "method": "POST"
        }
      },
      "description": "Rebuild a server from an image (returns a root password)",
      "resource": "server"
    },
    {
      "name": "Reset",
      "value": "reset",
      "action": "Reset a server",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/servers/{{ $parameter.serverId }}/actions/reset",
          "method": "POST"
        }
      },
      "description": "Cut power to and restart a server (hard reset)",
      "resource": "server"
    },
    {
      "name": "Reset Password",
      "value": "resetPassword",
      "action": "Reset the root password",
      "routing": {
        "request": {
          "url": "=/v1/servers/{{ $parameter.serverId }}/actions/reset_password",
          "method": "POST"
        }
      },
      "description": "Reset the root password of a server (returns a new root password)",
      "resource": "server"
    },
    {
      "name": "Shutdown",
      "value": "shutdown",
      "action": "Shut down a server",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/servers/{{ $parameter.serverId }}/actions/shutdown",
          "method": "POST"
        }
      },
      "description": "Send an ACPI shutdown request to a server",
      "resource": "server"
    },
    {
      "name": "Update",
      "value": "update",
      "action": "Update a server",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "server"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/servers/{{ $parameter.serverId }}",
          "method": "PUT"
        }
      },
      "description": "Update an existing server (name and labels)",
      "resource": "server"
    },
    {
      "name": "Create",
      "value": "create",
      "action": "Create an SSH key",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "ssh_key"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/ssh_keys",
          "method": "POST"
        }
      },
      "description": "Add a new SSH key to the project",
      "resource": "sshKey"
    },
    {
      "name": "Delete",
      "value": "delete",
      "action": "Delete an SSH key",
      "routing": {
        "request": {
          "url": "=/v1/ssh_keys/{{ $parameter.sshKeyId }}",
          "method": "DELETE"
        }
      },
      "description": "Delete an SSH key",
      "resource": "sshKey"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get an SSH key",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "ssh_key"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/ssh_keys/{{ $parameter.sshKeyId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single SSH key by ID",
      "resource": "sshKey"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many SSH keys",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "ssh_keys"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/ssh_keys",
          "method": "GET"
        }
      },
      "description": "List SSH keys in the project",
      "resource": "sshKey"
    },
    {
      "name": "Update",
      "value": "update",
      "action": "Update an SSH key",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "ssh_key"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/ssh_keys/{{ $parameter.sshKeyId }}",
          "method": "PUT"
        }
      },
      "description": "Update an existing SSH key (name and labels)",
      "resource": "sshKey"
    },
    {
      "name": "Attach",
      "value": "attach",
      "action": "Attach a volume to a server",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/volumes/{{ $parameter.volumeId }}/actions/attach",
          "method": "POST"
        }
      },
      "description": "Attach a volume to a server",
      "resource": "volume"
    },
    {
      "name": "Change Protection",
      "value": "changeProtection",
      "action": "Change volume protection",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/volumes/{{ $parameter.volumeId }}/actions/change_protection",
          "method": "POST"
        }
      },
      "description": "Change the delete protection of a volume",
      "resource": "volume"
    },
    {
      "name": "Create",
      "value": "create",
      "action": "Create a volume",
      "routing": {
        "request": {
          "url": "/v1/volumes",
          "method": "POST"
        }
      },
      "description": "Create a new volume",
      "resource": "volume"
    },
    {
      "name": "Delete",
      "value": "delete",
      "action": "Delete a volume",
      "routing": {
        "request": {
          "url": "=/v1/volumes/{{ $parameter.volumeId }}",
          "method": "DELETE"
        }
      },
      "description": "Delete a volume",
      "resource": "volume"
    },
    {
      "name": "Detach",
      "value": "detach",
      "action": "Detach a volume from its server",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/volumes/{{ $parameter.volumeId }}/actions/detach",
          "method": "POST"
        }
      },
      "description": "Detach a volume from the server it is attached to",
      "resource": "volume"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a volume",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "volume"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/volumes/{{ $parameter.volumeId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single volume by ID",
      "resource": "volume"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many volumes",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "volumes"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/volumes",
          "method": "GET"
        }
      },
      "description": "List volumes in the project",
      "resource": "volume"
    },
    {
      "name": "Resize",
      "value": "resize",
      "action": "Resize a volume",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/volumes/{{ $parameter.volumeId }}/actions/resize",
          "method": "POST"
        }
      },
      "description": "Increase the size of a volume",
      "resource": "volume"
    },
    {
      "name": "Update",
      "value": "update",
      "action": "Update a volume",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "volume"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/volumes/{{ $parameter.volumeId }}",
          "method": "PUT"
        }
      },
      "description": "Update an existing volume (name and labels)",
      "resource": "volume"
    },
    {
      "name": "Add Route",
      "value": "addRoute",
      "action": "Add a route to a network",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/networks/{{ $parameter.networkId }}/actions/add_route",
          "method": "POST"
        }
      },
      "description": "Add a route to a network",
      "resource": "network"
    },
    {
      "name": "Add Subnet",
      "value": "addSubnet",
      "action": "Add a subnet to a network",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/networks/{{ $parameter.networkId }}/actions/add_subnet",
          "method": "POST"
        }
      },
      "description": "Add a subnet to a network",
      "resource": "network"
    },
    {
      "name": "Change IP Range",
      "value": "changeIpRange",
      "action": "Change the IP range of a network",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/networks/{{ $parameter.networkId }}/actions/change_ip_range",
          "method": "POST"
        }
      },
      "description": "Change the IP range of a network",
      "resource": "network"
    },
    {
      "name": "Change Protection",
      "value": "changeProtection",
      "action": "Change network protection",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/networks/{{ $parameter.networkId }}/actions/change_protection",
          "method": "POST"
        }
      },
      "description": "Change the delete protection of a network",
      "resource": "network"
    },
    {
      "name": "Create",
      "value": "create",
      "action": "Create a network",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "network"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/networks",
          "method": "POST"
        }
      },
      "description": "Create a new network",
      "resource": "network"
    },
    {
      "name": "Delete",
      "value": "delete",
      "action": "Delete a network",
      "routing": {
        "request": {
          "url": "=/v1/networks/{{ $parameter.networkId }}",
          "method": "DELETE"
        }
      },
      "description": "Delete a network",
      "resource": "network"
    },
    {
      "name": "Delete Route",
      "value": "deleteRoute",
      "action": "Delete a route from a network",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/networks/{{ $parameter.networkId }}/actions/del_route",
          "method": "POST"
        }
      },
      "description": "Delete a route from a network",
      "resource": "network"
    },
    {
      "name": "Delete Subnet",
      "value": "deleteSubnet",
      "action": "Delete a subnet from a network",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/networks/{{ $parameter.networkId }}/actions/del_subnet",
          "method": "POST"
        }
      },
      "description": "Delete a subnet from a network",
      "resource": "network"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a network",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "network"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/networks/{{ $parameter.networkId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single network by ID",
      "resource": "network"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many networks",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "networks"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/networks",
          "method": "GET"
        }
      },
      "description": "List networks in the project",
      "resource": "network"
    },
    {
      "name": "Update",
      "value": "update",
      "action": "Update a network",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "network"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/networks/{{ $parameter.networkId }}",
          "method": "PUT"
        }
      },
      "description": "Update an existing network (name and labels)",
      "resource": "network"
    },
    {
      "name": "Apply to Resources",
      "value": "applyToResources",
      "action": "Apply a firewall to resources",
      "routing": {
        "send": {
          "preSend": [
            null
          ]
        },
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "actions"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/firewalls/{{ $parameter.firewallId }}/actions/apply_to_resources",
          "method": "POST"
        }
      },
      "description": "Apply the firewall to servers or label selectors",
      "resource": "firewall"
    },
    {
      "name": "Create",
      "value": "create",
      "action": "Create a firewall",
      "routing": {
        "send": {
          "preSend": [
            null,
            null
          ]
        },
        "request": {
          "url": "/v1/firewalls",
          "method": "POST"
        }
      },
      "description": "Create a new firewall",
      "resource": "firewall"
    },
    {
      "name": "Delete",
      "value": "delete",
      "action": "Delete a firewall",
      "routing": {
        "request": {
          "url": "=/v1/firewalls/{{ $parameter.firewallId }}",
          "method": "DELETE"
        }
      },
      "description": "Delete a firewall",
      "resource": "firewall"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a firewall",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "firewall"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/firewalls/{{ $parameter.firewallId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single firewall by ID",
      "resource": "firewall"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many firewalls",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "firewalls"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/firewalls",
          "method": "GET"
        }
      },
      "description": "List firewalls in the project",
      "resource": "firewall"
    },
    {
      "name": "Remove From Resources",
      "value": "removeFromResources",
      "action": "Remove a firewall from resources",
      "routing": {
        "send": {
          "preSend": [
            null
          ]
        },
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "actions"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/firewalls/{{ $parameter.firewallId }}/actions/remove_from_resources",
          "method": "POST"
        }
      },
      "description": "Remove the firewall from servers or label selectors",
      "resource": "firewall"
    },
    {
      "name": "Set Rules",
      "value": "setRules",
      "action": "Set firewall rules",
      "routing": {
        "send": {
          "preSend": [
            null
          ]
        },
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "actions"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/firewalls/{{ $parameter.firewallId }}/actions/set_rules",
          "method": "POST"
        }
      },
      "description": "Replace all rules of a firewall",
      "resource": "firewall"
    },
    {
      "name": "Update",
      "value": "update",
      "action": "Update a firewall",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "firewall"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/firewalls/{{ $parameter.firewallId }}",
          "method": "PUT"
        }
      },
      "description": "Update an existing firewall (name and labels)",
      "resource": "firewall"
    },
    {
      "name": "Add Service",
      "value": "addService",
      "action": "Add a service to a load balancer",
      "routing": {
        "send": {
          "preSend": [
            null
          ]
        },
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/load_balancers/{{ $parameter.loadBalancerId }}/actions/add_service",
          "method": "POST"
        }
      },
      "description": "Add a service to a load balancer",
      "resource": "loadBalancer"
    },
    {
      "name": "Add Target",
      "value": "addTarget",
      "action": "Add a target to a load balancer",
      "routing": {
        "send": {
          "preSend": [
            null
          ]
        },
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/load_balancers/{{ $parameter.loadBalancerId }}/actions/add_target",
          "method": "POST"
        }
      },
      "description": "Add a target to a load balancer",
      "resource": "loadBalancer"
    },
    {
      "name": "Change Algorithm",
      "value": "changeAlgorithm",
      "action": "Change the load balancer algorithm",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/load_balancers/{{ $parameter.loadBalancerId }}/actions/change_algorithm",
          "method": "POST"
        }
      },
      "description": "Change the algorithm of a load balancer",
      "resource": "loadBalancer"
    },
    {
      "name": "Change Protection",
      "value": "changeProtection",
      "action": "Change load balancer protection",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/load_balancers/{{ $parameter.loadBalancerId }}/actions/change_protection",
          "method": "POST"
        }
      },
      "description": "Change the delete protection of a load balancer",
      "resource": "loadBalancer"
    },
    {
      "name": "Change Type",
      "value": "changeType",
      "action": "Change the load balancer type",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/load_balancers/{{ $parameter.loadBalancerId }}/actions/change_type",
          "method": "POST"
        }
      },
      "description": "Change the type of a load balancer",
      "resource": "loadBalancer"
    },
    {
      "name": "Create",
      "value": "create",
      "action": "Create a load balancer",
      "routing": {
        "request": {
          "url": "/v1/load_balancers",
          "method": "POST"
        }
      },
      "description": "Create a new load balancer",
      "resource": "loadBalancer"
    },
    {
      "name": "Delete",
      "value": "delete",
      "action": "Delete a load balancer",
      "routing": {
        "request": {
          "url": "=/v1/load_balancers/{{ $parameter.loadBalancerId }}",
          "method": "DELETE"
        }
      },
      "description": "Delete a load balancer",
      "resource": "loadBalancer"
    },
    {
      "name": "Delete Service",
      "value": "deleteService",
      "action": "Delete a service from a load balancer",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/load_balancers/{{ $parameter.loadBalancerId }}/actions/delete_service",
          "method": "POST"
        }
      },
      "description": "Delete a service from a load balancer",
      "resource": "loadBalancer"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a load balancer",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "load_balancer"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/load_balancers/{{ $parameter.loadBalancerId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single load balancer by ID",
      "resource": "loadBalancer"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many load balancers",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "load_balancers"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/load_balancers",
          "method": "GET"
        }
      },
      "description": "List load balancers in the project",
      "resource": "loadBalancer"
    },
    {
      "name": "Remove Target",
      "value": "removeTarget",
      "action": "Remove a target from a load balancer",
      "routing": {
        "send": {
          "preSend": [
            null
          ]
        },
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/load_balancers/{{ $parameter.loadBalancerId }}/actions/remove_target",
          "method": "POST"
        }
      },
      "description": "Remove a target from a load balancer",
      "resource": "loadBalancer"
    },
    {
      "name": "Update",
      "value": "update",
      "action": "Update a load balancer",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "load_balancer"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/load_balancers/{{ $parameter.loadBalancerId }}",
          "method": "PUT"
        }
      },
      "description": "Update an existing load balancer (name and labels)",
      "resource": "loadBalancer"
    },
    {
      "name": "Assign",
      "value": "assign",
      "action": "Assign a floating ip to a server",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/floating_ips/{{ $parameter.floatingIpId }}/actions/assign",
          "method": "POST"
        }
      },
      "description": "Assign a Floating IP to a server",
      "resource": "floatingIp"
    },
    {
      "name": "Change DNS PTR",
      "value": "changeDnsPtr",
      "action": "Change the reverse dns of a floating ip",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/floating_ips/{{ $parameter.floatingIpId }}/actions/change_dns_ptr",
          "method": "POST"
        }
      },
      "description": "Change the reverse DNS (PTR) entry of a Floating IP",
      "resource": "floatingIp"
    },
    {
      "name": "Change Protection",
      "value": "changeProtection",
      "action": "Change floating ip protection",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/floating_ips/{{ $parameter.floatingIpId }}/actions/change_protection",
          "method": "POST"
        }
      },
      "description": "Change the delete protection of a Floating IP",
      "resource": "floatingIp"
    },
    {
      "name": "Create",
      "value": "create",
      "action": "Create a floating ip",
      "routing": {
        "request": {
          "url": "/v1/floating_ips",
          "method": "POST"
        }
      },
      "description": "Create a new Floating IP",
      "resource": "floatingIp"
    },
    {
      "name": "Delete",
      "value": "delete",
      "action": "Delete a floating ip",
      "routing": {
        "request": {
          "url": "=/v1/floating_ips/{{ $parameter.floatingIpId }}",
          "method": "DELETE"
        }
      },
      "description": "Delete a Floating IP",
      "resource": "floatingIp"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a floating ip",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "floating_ip"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/floating_ips/{{ $parameter.floatingIpId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single Floating IP by ID",
      "resource": "floatingIp"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many floating ips",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "floating_ips"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/floating_ips",
          "method": "GET"
        }
      },
      "description": "List Floating IPs in the project",
      "resource": "floatingIp"
    },
    {
      "name": "Unassign",
      "value": "unassign",
      "action": "Unassign a floating ip",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/floating_ips/{{ $parameter.floatingIpId }}/actions/unassign",
          "method": "POST"
        }
      },
      "description": "Unassign a Floating IP from its server",
      "resource": "floatingIp"
    },
    {
      "name": "Update",
      "value": "update",
      "action": "Update a floating ip",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "floating_ip"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/floating_ips/{{ $parameter.floatingIpId }}",
          "method": "PUT"
        }
      },
      "description": "Update an existing Floating IP (name, description, labels)",
      "resource": "floatingIp"
    },
    {
      "name": "Assign",
      "value": "assign",
      "action": "Assign a primary ip to a server",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/primary_ips/{{ $parameter.primaryIpId }}/actions/assign",
          "method": "POST"
        }
      },
      "description": "Assign a Primary IP to a server",
      "resource": "primaryIp"
    },
    {
      "name": "Change DNS PTR",
      "value": "changeDnsPtr",
      "action": "Change the reverse dns of a primary ip",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/primary_ips/{{ $parameter.primaryIpId }}/actions/change_dns_ptr",
          "method": "POST"
        }
      },
      "description": "Change the reverse DNS (PTR) entry of a Primary IP",
      "resource": "primaryIp"
    },
    {
      "name": "Change Protection",
      "value": "changeProtection",
      "action": "Change primary ip protection",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/primary_ips/{{ $parameter.primaryIpId }}/actions/change_protection",
          "method": "POST"
        }
      },
      "description": "Change the delete protection of a Primary IP",
      "resource": "primaryIp"
    },
    {
      "name": "Create",
      "value": "create",
      "action": "Create a primary ip",
      "routing": {
        "request": {
          "url": "/v1/primary_ips",
          "method": "POST"
        }
      },
      "description": "Create a new Primary IP",
      "resource": "primaryIp"
    },
    {
      "name": "Delete",
      "value": "delete",
      "action": "Delete a primary ip",
      "routing": {
        "request": {
          "url": "=/v1/primary_ips/{{ $parameter.primaryIpId }}",
          "method": "DELETE"
        }
      },
      "description": "Delete a Primary IP",
      "resource": "primaryIp"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a primary ip",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "primary_ip"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/primary_ips/{{ $parameter.primaryIpId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single Primary IP by ID",
      "resource": "primaryIp"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many primary ips",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "primary_ips"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/primary_ips",
          "method": "GET"
        }
      },
      "description": "List Primary IPs in the project",
      "resource": "primaryIp"
    },
    {
      "name": "Unassign",
      "value": "unassign",
      "action": "Unassign a primary ip",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/primary_ips/{{ $parameter.primaryIpId }}/actions/unassign",
          "method": "POST"
        }
      },
      "description": "Unassign a Primary IP from its server",
      "resource": "primaryIp"
    },
    {
      "name": "Update",
      "value": "update",
      "action": "Update a primary ip",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "primary_ip"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/primary_ips/{{ $parameter.primaryIpId }}",
          "method": "PUT"
        }
      },
      "description": "Update an existing Primary IP (name, labels, auto-delete)",
      "resource": "primaryIp"
    },
    {
      "name": "Create",
      "value": "create",
      "action": "Create a certificate",
      "routing": {
        "request": {
          "url": "/v1/certificates",
          "method": "POST"
        }
      },
      "description": "Upload or request a managed certificate",
      "resource": "certificate"
    },
    {
      "name": "Delete",
      "value": "delete",
      "action": "Delete a certificate",
      "routing": {
        "request": {
          "url": "=/v1/certificates/{{ $parameter.certificateId }}",
          "method": "DELETE"
        }
      },
      "description": "Delete a certificate",
      "resource": "certificate"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a certificate",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "certificate"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/certificates/{{ $parameter.certificateId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single certificate by ID",
      "resource": "certificate"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many certificates",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "certificates"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/certificates",
          "method": "GET"
        }
      },
      "description": "List certificates in the project",
      "resource": "certificate"
    },
    {
      "name": "Retry",
      "value": "retry",
      "action": "Retry a managed certificate",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/certificates/{{ $parameter.certificateId }}/actions/retry",
          "method": "POST"
        }
      },
      "description": "Retry issuance of a failed managed certificate",
      "resource": "certificate"
    },
    {
      "name": "Update",
      "value": "update",
      "action": "Update a certificate",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "certificate"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/certificates/{{ $parameter.certificateId }}",
          "method": "PUT"
        }
      },
      "description": "Update an existing certificate (name and labels)",
      "resource": "certificate"
    },
    {
      "name": "Change Protection",
      "value": "changeProtection",
      "action": "Change image protection",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/images/{{ $parameter.imageId }}/actions/change_protection",
          "method": "POST"
        }
      },
      "description": "Change the delete protection of an image",
      "resource": "image"
    },
    {
      "name": "Delete",
      "value": "delete",
      "action": "Delete an image",
      "routing": {
        "request": {
          "url": "=/v1/images/{{ $parameter.imageId }}",
          "method": "DELETE"
        }
      },
      "description": "Delete an image (snapshot or backup)",
      "resource": "image"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get an image",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "image"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/images/{{ $parameter.imageId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single image by ID",
      "resource": "image"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many images",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "images"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/images",
          "method": "GET"
        }
      },
      "description": "List images available to the project",
      "resource": "image"
    },
    {
      "name": "Update",
      "value": "update",
      "action": "Update an image",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "image"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/images/{{ $parameter.imageId }}",
          "method": "PUT"
        }
      },
      "description": "Update an existing image (description, type, labels)",
      "resource": "image"
    },
    {
      "name": "Create",
      "value": "create",
      "action": "Create a placement group",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "placement_group"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/placement_groups",
          "method": "POST"
        }
      },
      "description": "Create a new placement group",
      "resource": "placementGroup"
    },
    {
      "name": "Delete",
      "value": "delete",
      "action": "Delete a placement group",
      "routing": {
        "request": {
          "url": "=/v1/placement_groups/{{ $parameter.placementGroupId }}",
          "method": "DELETE"
        }
      },
      "description": "Delete a placement group",
      "resource": "placementGroup"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a placement group",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "placement_group"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/placement_groups/{{ $parameter.placementGroupId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single placement group by ID",
      "resource": "placementGroup"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many placement groups",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "placement_groups"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/placement_groups",
          "method": "GET"
        }
      },
      "description": "List placement groups in the project",
      "resource": "placementGroup"
    },
    {
      "name": "Update",
      "value": "update",
      "action": "Update a placement group",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "placement_group"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/placement_groups/{{ $parameter.placementGroupId }}",
          "method": "PUT"
        }
      },
      "description": "Update an existing placement group (name and labels)",
      "resource": "placementGroup"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a server type",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "server_type"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/server_types/{{ $parameter.serverTypeId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single server type by ID",
      "resource": "serverType"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many server types",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "server_types"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/server_types",
          "method": "GET"
        }
      },
      "description": "List the available server types",
      "resource": "serverType"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a load balancer type",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "load_balancer_type"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/load_balancer_types/{{ $parameter.loadBalancerTypeId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single load balancer type by ID",
      "resource": "loadBalancerType"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many load balancer types",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "load_balancer_types"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/load_balancer_types",
          "method": "GET"
        }
      },
      "description": "List the available load balancer types",
      "resource": "loadBalancerType"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a datacenter",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "datacenter"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/datacenters/{{ $parameter.datacenterId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single datacenter by ID",
      "resource": "datacenter"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many datacenters",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "datacenters"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/datacenters",
          "method": "GET"
        }
      },
      "description": "List the available datacenters",
      "resource": "datacenter"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a location",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "location"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/locations/{{ $parameter.locationId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single location by ID",
      "resource": "location"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many locations",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "locations"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/locations",
          "method": "GET"
        }
      },
      "description": "List the available locations",
      "resource": "location"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get an ISO",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "iso"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/isos/{{ $parameter.isoId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single ISO by ID",
      "resource": "iso"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many isos",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "isos"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/isos",
          "method": "GET"
        }
      },
      "description": "List the available ISOs",
      "resource": "iso"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get an action",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "action"
              }
            }
          ]
        },
        "request": {
          "url": "=/v1/actions/{{ $parameter.actionId }}",
          "method": "GET"
        }
      },
      "description": "Retrieve a single action by ID",
      "resource": "action"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many actions",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "actions"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/actions",
          "method": "GET"
        }
      },
      "description": "List actions across many resources",
      "resource": "action"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get pricing",
      "routing": {
        "output": {
          "postReceive": [
            {
              "type": "rootProperty",
              "properties": {
                "property": "pricing"
              }
            }
          ]
        },
        "request": {
          "url": "/v1/pricing",
          "method": "GET"
        }
      },
      "description": "Retrieve current prices for all resources",
      "resource": "pricing"
    }
  ]

npm_readme:
  # n8n-nodes-hetzner-cloud

  This is an n8n community node. It lets you use the [Hetzner Cloud](https://www.hetzner.com/cloud) API in your n8n workflows.

  Hetzner Cloud is an infrastructure-as-a-service platform for provisioning cloud servers, volumes, networks, load balancers and more.

  [n8n](https://n8n.io/) is a [fair-code licensed](https://docs.n8n.io/reference/license/) workflow automation platform.

  [Installation](#installation)
  [Credentials](#credentials)
  [Operations](#operations)
  [Compatibility](#compatibility)
  [Resources](#resources)

  ## Installation

  Follow the [installation guide](https://docs.n8n.io/integrations/community-nodes/installation/) in the n8n community nodes documentation.

  Install the package `@mookielianhd/n8n-nodes-hetzner-cloud`.

  ## Credentials

  You need a Hetzner Cloud **API token**:

  1. Sign in to the [Hetzner Cloud Console](https://console.hetzner.cloud/).
  2. Select your project, then go to **Security → API tokens**.
  3. Click **Generate API token**, give it Read & Write permissions, and copy the token (it is shown only once).
  4. In n8n, create a new **Hetzner Cloud API** credential and paste the token.

  API tokens are scoped to a single project. Use the **Test Connection** button to verify the token.

  ## Operations

  The node exposes the following resources:

  | Resource | Operations |
  | --- | --- |
  | Server | Create, Get, Get Many, Update, Delete, Power On/Off, Reboot, Reset, Shutdown, Rebuild, Change Type, Create Image, Enable/Disable Rescue, Attach/Detach ISO, Reset Password, Change Protection |
  | SSH Key | Create, Get, Get Many, Update, Delete |
  | Volume | Create, Get, Get Many, Update, Delete, Attach, Detach, Resize, Change Protection |
  | Network | Create, Get, Get Many, Update, Delete, Add/Delete Subnet, Add/Delete Route, Change IP Range, Change Protection |
  | Firewall | Create, Get, Get Many, Update, Delete, Set Rules, Apply to / Remove from Resources |
  | Load Balancer | Create, Get, Get Many, Update, Delete, Add/Delete Service, Add/Remove Target, Change Algorithm/Type/Protection |
  | Floating IP | Create, Get, Get Many, Update, Delete, Assign, Unassign, Change DNS PTR, Change Protection |
  | Primary IP | Create, Get, Get Many, Update, Delete, Assign, Unassign, Change DNS PTR, Change Protection |
  | Certificate | Create, Get, Get Many, Update, Delete, Retry |
  | Image | Get, Get Many, Update, Delete, Change Protection |
  | Placement Group | Create, Get, Get Many, Update, Delete |
  | Server Type, Load Balancer Type, Datacenter, Location, ISO, Action | Get, Get Many (read-only) |
  | Pricing | Get (read-only) |

  Most create/action operations on servers, volumes and similar resources return an asynchronous
  **Action** object alongside the resource — poll the **Action** resource to track completion.

  Fields that aren't exposed directly can be set via the **Additional Body Fields (JSON)** input on
  create/update operations. See the [Hetzner Cloud API reference](https://docs.hetzner.cloud/).

  ## Compatibility

  Requires n8n with `n8nNodesApiVersion` 1. Tested against the Hetzner Cloud API v1.

  ## Resources

  - [Hetzner Cloud API documentation](https://docs.hetzner.cloud/)
  - [n8n community nodes documentation](https://docs.n8n.io/integrations/#community-nodes)

ai_documentation_summary:
  {"purpose":"This node integrates n8n with the Hetzner Cloud API so workflows can provision and manage cloud infrastructure such as servers, volumes, networks, load balancers, IPs, and related resources. It supports both resource management and read-only lookup operations.","capabilities":["Manage servers: create, get, list, update, delete, power on/off, reboot, reset, shutdown, rebuild, change type, create image, enable/disable rescue, attach/detach ISO, reset password, change protection","Manage SSH keys: create, get, list, update, delete","Manage volumes: create, get, list, update, delete, attach, detach, resize, change protection","Manage networks: create, get, list, update, delete, add/delete subnet, add/delete route, change IP range, change protection","Manage firewalls: create, get, list, update, delete, set rules, apply/remove from resources","Manage load balancers: create, get, list, update, delete, add/delete service, add/remove target, change algorithm/type/protection","Manage floating IPs and primary IPs: create, get, list, update, delete, assign/unassign, change DNS PTR, change protection","Manage certificates: create, get, list, update, delete, retry","Manage images: get, list, update, delete, change protection","Manage placement groups: create, get, list, update, delete"],"authentication":"Hetzner Cloud API token required; create a Hetzner Cloud API credential in n8n and paste the token (read/write permissions, project-scoped).","commonUseCases":["Provisioning and managing Hetzner Cloud servers and associated infrastructure in automated workflows","Creating and attaching volumes, IPs, networks, firewalls, and load balancer resources","Monitoring completion of long-running Hetzner Cloud actions from n8n","Retrieving cloud metadata such as datacenters, locations, server types, and pricing"],"limitations":["API tokens are scoped to a single Hetzner Cloud project","Many create/action operations are asynchronous and require polling the Action resource for completion","Some fields are not exposed directly and must be provided via Additional Body Fields (JSON)","Requires n8nNodesApiVersion 1"],"relatedNodes":[]}


node_type: @testdino/n8n-nodes-testdino.testDino
package_name: @testdino/n8n-nodes-testdino
display_name: TestDino
description: Query TestDino test runs, test cases, specs, analytics, and reports
category: Community
development_style: declarative
version: 1
credentials_required: []
outputs:
  [
  "main"
  ]

updated_at: 2026-07-14 14:40:34
author_name: testdino.npm
author_github_url: https://github.com/testdino-hq/n8n-nodes-testdino.git
npm_package_name: @testdino/n8n-nodes-testdino
npm_version: 0.1.6
community_fetched_at: 2026-07-14T14:40:34.480Z
ai_summary_generated_at: 2026-06-26 10:29:17
properties_schema:
  [
    {
      "name": "resource",
      "type": "options",
      "default": "testRun",
      "options": [
        {
          "name": "Analytics",
          "value": "analytics"
        },
        {
          "name": "Dashboard",
          "value": "dashboard"
        },
        {
          "name": "Filter",
          "value": "filter"
        },
        {
          "name": "Manual Test",
          "value": "manualTest"
        },
        {
          "name": "Report",
          "value": "report"
        },
        {
          "name": "Spec",
          "value": "spec"
        },
        {
          "name": "Test Case",
          "value": "testCase"
        },
        {
          "name": "Test Run",
          "value": "testRun"
        },
        {
          "name": "Usage",
          "value": "usage"
        }
      ],
      "displayName": "Resource",
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Get",
          "value": "get",
          "action": "Get a test run",
          "description": "Get a single test run by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many test runs",
          "description": "List test runs with optional filters"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "testRun"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "explore",
      "options": [
        {
          "name": "Explore",
          "value": "explore",
          "action": "Explore aggregated test cases",
          "description": "Aggregated metrics across runs"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get a test case",
          "description": "Get a single test case by ID"
        },
        {
          "name": "Get History",
          "value": "history",
          "action": "Get test case history",
          "description": "Execution history for a test case by title"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "testCase"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many specs",
          "description": "List spec files with health metrics"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "spec"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getAll",
      "options": [
        {
          "name": "Get",
          "value": "get",
          "action": "Get a manual test case",
          "description": "Get a single manual test case by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many manual test cases",
          "description": "List manual test cases"
        },
        {
          "name": "Get Suites",
          "value": "getSuites",
          "action": "Get manual test suites",
          "description": "List manual test suites"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "manualTest"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "get",
      "options": [
        {
          "name": "Get",
          "value": "get",
          "action": "Get the project dashboard",
          "description": "Project health overview"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "dashboard"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getSummary",
      "options": [
        {
          "name": "Get Summary",
          "value": "getSummary",
          "action": "Get analytics summary",
          "description": "Summary metrics and performance trends"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "analytics"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "get",
      "options": [
        {
          "name": "Get",
          "value": "get",
          "action": "Get usage",
          "description": "Subscription usage and project allocation"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "usage"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "get",
      "options": [
        {
          "name": "Get",
          "value": "get",
          "action": "Get available filters",
          "description": "Discover environments, branches, developers, and tags"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "filter"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "generatePdf",
      "options": [
        {
          "name": "Generate PDF",
          "value": "generatePdf",
          "action": "Generate a PDF report",
          "description": "Generate and download a project report PDF"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "report"
          ]
        }
      },
      "noDataExpression": true
    }
  ]

operations:
  [
    {
      "name": "Get",
      "value": "get",
      "action": "Get a test run",
      "description": "Get a single test run by ID",
      "resource": "testRun"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many test runs",
      "description": "List test runs with optional filters",
      "resource": "testRun"
    },
    {
      "name": "Explore",
      "value": "explore",
      "action": "Explore aggregated test cases",
      "description": "Aggregated metrics across runs",
      "resource": "testCase"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a test case",
      "description": "Get a single test case by ID",
      "resource": "testCase"
    },
    {
      "name": "Get History",
      "value": "history",
      "action": "Get test case history",
      "description": "Execution history for a test case by title",
      "resource": "testCase"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many specs",
      "description": "List spec files with health metrics",
      "resource": "spec"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a manual test case",
      "description": "Get a single manual test case by ID",
      "resource": "manualTest"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many manual test cases",
      "description": "List manual test cases",
      "resource": "manualTest"
    },
    {
      "name": "Get Suites",
      "value": "getSuites",
      "action": "Get manual test suites",
      "description": "List manual test suites",
      "resource": "manualTest"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get the project dashboard",
      "description": "Project health overview",
      "resource": "dashboard"
    },
    {
      "name": "Get Summary",
      "value": "getSummary",
      "action": "Get analytics summary",
      "description": "Summary metrics and performance trends",
      "resource": "analytics"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get usage",
      "description": "Subscription usage and project allocation",
      "resource": "usage"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get available filters",
      "description": "Discover environments, branches, developers, and tags",
      "resource": "filter"
    },
    {
      "name": "Generate PDF",
      "value": "generatePdf",
      "action": "Generate a PDF report",
      "description": "Generate and download a project report PDF",
      "resource": "report"
    }
  ]

npm_readme:
  # @testdino/n8n-nodes-testdino

  [![npm version](https://img.shields.io/npm/v/@testdino/n8n-nodes-testdino.svg)](https://www.npmjs.com/package/@testdino/n8n-nodes-testdino)
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/testdino-hq/n8n-nodes-testdino/blob/main/LICENSE)

  n8n community node for [TestDino](https://testdino.com) — automate workflows from Playwright test run events and query test analytics.

  Trigger workflows when a test run starts or finishes, query test runs, test cases, specs, analytics, and usage, and generate PDF reports. Both nodes are usable as AI-agent tools inside n8n's AI Agent node.

  ## Installation

  ### From the n8n UI

  1. Go to **Settings → Community Nodes → Install**.
  2. Enter the package name and confirm:

     ```
     @testdino/n8n-nodes-testdino
     ```

  3. Restart n8n if prompted.

  Browse the node on [n8n's integrations directory](https://n8n.io/integrations/?q=testdino).

  ### Self-hosted (manual)

  ```bash
  npm install @testdino/n8n-nodes-testdino
  ```

  Then restart n8n.

  **Requirements:** n8n with community nodes enabled · Node.js ≥ 18 · a TestDino account, project, and a `public-api`-scoped Personal Access Token.

  ## Credentials

  The **TestDino API** credential holds one field — your Personal Access Token (PAT). The project is discovered from the token, so you never enter a project ID.

  1. In TestDino, open **Project Settings → API**.
  2. Create a Personal Access Token with the `public-api` scope.
  3. Copy the token (format `tdp_…`). It is shown once.
  4. In n8n, go to **Credentials → New → TestDino API**, paste the token, then **Save** and **Test**.

  The **Test** button validates the token and resolves the bound project.

  > One token connects one project. Store it in a password manager, never commit it to Git, and revoke tokens you no longer use.

  ## Nodes

  This package ships two nodes and one credential type.

  | Node | Type | Purpose |
  | --- | --- | --- |
  | **TestDino** | Action / query | Read runs, cases, specs, analytics, usage; generate PDF reports |
  | **TestDino Trigger** | Webhook trigger | Start workflows on test run events |

  ### TestDino — resources & operations

  | Resource | Operations |
  | --- | --- |
  | Test Run | Get, Get Many |
  | Test Case | Get, Explore, Get History |
  | Spec | Get Many |
  | Manual Test | Get, Get Many, Get Suites |
  | Dashboard | Get |
  | Analytics | Get Summary |
  | Usage | Get |
  | Report | Generate PDF |

  List operations support **Return All** (walk every page) or a **Limit** (single page). **Generate PDF** returns a binary file you can attach in a later node.

  ### TestDino Trigger — events

  | Event | Fires when |
  | --- | --- |
  | Run Started | A new test run is created |
  | Run Finished | A test run completes |

  For **Run Finished**, set **Trigger On** to scope the event:

  | Trigger On | Behavior |
  | --- | --- |
  | Any Outcome | Every finished run |
  | Failures Only | Only runs with failures |
  | Passing Only | Only runs with no failures |

  The outcome filter is applied server-side, so failure-only alerts need no extra IF node. The node self-registers its webhook with TestDino when the workflow is activated, and the lifecycle is idempotent across n8n restarts.

  > The n8n instance must expose a publicly reachable production webhook URL for events to arrive.

  ## Use as AI-agent tools

  Both nodes set `usableAsTool: true`, so n8n's **AI Agent** node can call them directly. An agent can fetch recent failed runs, summarize release health, or generate a report on request. The operation descriptions double as the tool descriptions the agent reads.

  ## Example workflows

  **Failed-run Slack alert**

  ```
  TestDino Trigger (Run Finished, Failures only)
    → TestDino (Test Run, Get)
    → Slack
  ```

  **Weekly quality report**

  ```
  Schedule Trigger (Monday)
    → TestDino (Report, Generate PDF)
    → TestDino (Analytics, Get Summary)
    → Gmail
  ```

  **Usage monitor**

  ```
  Schedule Trigger (Daily)
    → TestDino (Usage, Get)
    → IF usage > 80%
    → Slack warning
  ```

  ## Troubleshooting

  | Symptom | Checks |
  | --- | --- |
  | Credential test fails | Token starts with `tdp_`, copied in full, has the `public-api` scope, not revoked. |
  | Trigger never fires | Workflow is **active**; production webhook URL is publicly reachable; no firewall blocking; token valid; outcome filter not excluding the run. |
  | Node missing in n8n | Package installed; community nodes enabled; n8n restarted; package name exact. |
  | Return All too slow | Disable Return All; use filters or a Limit instead. |

  ## Links

  - Documentation: https://docs.testdino.com/integrations/automation/n8n
  - API Reference: https://docs.testdino.com/api-reference/overview
  - App: https://app.testdino.com
  - Repository: https://github.com/testdino-hq/n8n-nodes-testdino
  - Support: support@testdino.com

  ## License

  [MIT](https://github.com/testdino-hq/n8n-nodes-testdino/blob/main/LICENSE)

ai_documentation_summary:
  {"purpose":"TestDino is an n8n community node for querying TestDino test data and generating reports, plus a trigger node for starting workflows from Playwright test run events. It supports reading runs, cases, specs, analytics, usage, and PDF report generation.","capabilities":["Get and list test runs","Get, explore, and retrieve history for test cases","Get many specs","Get, list, and retrieve suites for manual tests","Get dashboard data","Get analytics summary","Get usage data","Generate PDF reports","Trigger workflows on run started events","Trigger workflows on run finished events with Any Outcome, Failures Only, or Passing Only filtering"],"authentication":"Personal Access Token (PAT) using the TestDino API credential; requires a public-api-scoped token and the project is discovered from the token","commonUseCases":["Alerting on failed test runs in Slack or other tools","Generating scheduled quality or analytics reports","Monitoring usage thresholds and sending warnings","Fetching recent test run or test case data for AI Agent workflows"],"limitations":["Requires a publicly reachable production webhook URL for trigger events","One token connects to one project","List operations may require Return All or a Limit, and Return All can be slow","Trigger workflows must be active for events to fire"],"relatedNodes":["TestDino Trigger","AI Agent","Slack","Gmail","IF"]}


node_type: @testdino/n8n-nodes-testdino.testDinoTrigger
package_name: @testdino/n8n-nodes-testdino
display_name: TestDino Trigger
description: Starts the workflow when a TestDino test run event occurs
category: Community
development_style: declarative
version: 1
properties_schema: []
operations: []
credentials_required: []
outputs:
  [
  "main"
  ]

updated_at: 2026-07-14 14:40:34
author_name: testdino.npm
author_github_url: https://github.com/testdino-hq/n8n-nodes-testdino.git
npm_package_name: @testdino/n8n-nodes-testdino
npm_version: 0.1.6
community_fetched_at: 2026-07-14T14:40:34.481Z
ai_summary_generated_at: 2026-06-26 10:29:17
npm_readme:
  # @testdino/n8n-nodes-testdino

  [![npm version](https://img.shields.io/npm/v/@testdino/n8n-nodes-testdino.svg)](https://www.npmjs.com/package/@testdino/n8n-nodes-testdino)
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/testdino-hq/n8n-nodes-testdino/blob/main/LICENSE)

  n8n community node for [TestDino](https://testdino.com) — automate workflows from Playwright test run events and query test analytics.

  Trigger workflows when a test run starts or finishes, query test runs, test cases, specs, analytics, and usage, and generate PDF reports. Both nodes are usable as AI-agent tools inside n8n's AI Agent node.

  ## Installation

  ### From the n8n UI

  1. Go to **Settings → Community Nodes → Install**.
  2. Enter the package name and confirm:

     ```
     @testdino/n8n-nodes-testdino
     ```

  3. Restart n8n if prompted.

  Browse the node on [n8n's integrations directory](https://n8n.io/integrations/?q=testdino).

  ### Self-hosted (manual)

  ```bash
  npm install @testdino/n8n-nodes-testdino
  ```

  Then restart n8n.

  **Requirements:** n8n with community nodes enabled · Node.js ≥ 18 · a TestDino account, project, and a `public-api`-scoped Personal Access Token.

  ## Credentials

  The **TestDino API** credential holds one field — your Personal Access Token (PAT). The project is discovered from the token, so you never enter a project ID.

  1. In TestDino, open **Project Settings → API**.
  2. Create a Personal Access Token with the `public-api` scope.
  3. Copy the token (format `tdp_…`). It is shown once.
  4. In n8n, go to **Credentials → New → TestDino API**, paste the token, then **Save** and **Test**.

  The **Test** button validates the token and resolves the bound project.

  > One token connects one project. Store it in a password manager, never commit it to Git, and revoke tokens you no longer use.

  ## Nodes

  This package ships two nodes and one credential type.

  | Node | Type | Purpose |
  | --- | --- | --- |
  | **TestDino** | Action / query | Read runs, cases, specs, analytics, usage; generate PDF reports |
  | **TestDino Trigger** | Webhook trigger | Start workflows on test run events |

  ### TestDino — resources & operations

  | Resource | Operations |
  | --- | --- |
  | Test Run | Get, Get Many |
  | Test Case | Get, Explore, Get History |
  | Spec | Get Many |
  | Manual Test | Get, Get Many, Get Suites |
  | Dashboard | Get |
  | Analytics | Get Summary |
  | Usage | Get |
  | Report | Generate PDF |

  List operations support **Return All** (walk every page) or a **Limit** (single page). **Generate PDF** returns a binary file you can attach in a later node.

  ### TestDino Trigger — events

  | Event | Fires when |
  | --- | --- |
  | Run Started | A new test run is created |
  | Run Finished | A test run completes |

  For **Run Finished**, set **Trigger On** to scope the event:

  | Trigger On | Behavior |
  | --- | --- |
  | Any Outcome | Every finished run |
  | Failures Only | Only runs with failures |
  | Passing Only | Only runs with no failures |

  The outcome filter is applied server-side, so failure-only alerts need no extra IF node. The node self-registers its webhook with TestDino when the workflow is activated, and the lifecycle is idempotent across n8n restarts.

  > The n8n instance must expose a publicly reachable production webhook URL for events to arrive.

  ## Use as AI-agent tools

  Both nodes set `usableAsTool: true`, so n8n's **AI Agent** node can call them directly. An agent can fetch recent failed runs, summarize release health, or generate a report on request. The operation descriptions double as the tool descriptions the agent reads.

  ## Example workflows

  **Failed-run Slack alert**

  ```
  TestDino Trigger (Run Finished, Failures only)
    → TestDino (Test Run, Get)
    → Slack
  ```

  **Weekly quality report**

  ```
  Schedule Trigger (Monday)
    → TestDino (Report, Generate PDF)
    → TestDino (Analytics, Get Summary)
    → Gmail
  ```

  **Usage monitor**

  ```
  Schedule Trigger (Daily)
    → TestDino (Usage, Get)
    → IF usage > 80%
    → Slack warning
  ```

  ## Troubleshooting

  | Symptom | Checks |
  | --- | --- |
  | Credential test fails | Token starts with `tdp_`, copied in full, has the `public-api` scope, not revoked. |
  | Trigger never fires | Workflow is **active**; production webhook URL is publicly reachable; no firewall blocking; token valid; outcome filter not excluding the run. |
  | Node missing in n8n | Package installed; community nodes enabled; n8n restarted; package name exact. |
  | Return All too slow | Disable Return All; use filters or a Limit instead. |

  ## Links

  - Documentation: https://docs.testdino.com/integrations/automation/n8n
  - API Reference: https://docs.testdino.com/api-reference/overview
  - App: https://app.testdino.com
  - Repository: https://github.com/testdino-hq/n8n-nodes-testdino
  - Support: support@testdino.com

  ## License

  [MIT](https://github.com/testdino-hq/n8n-nodes-testdino/blob/main/LICENSE)

ai_documentation_summary:
  {"purpose":"Connects n8n to TestDino so workflows can react to test run events and query test analytics data. The package includes a trigger for run events and an action/query node for reading runs, cases, specs, analytics, usage, and generating PDF reports.","capabilities":["Trigger workflows when a test run starts","Trigger workflows when a test run finishes","Filter finished-run triggers by any outcome, failures only, or passing only","Get many test runs with Return All or Limit support","Get a single test run","Get a single test case","Explore test cases","Get test case history","Get many specs","Get a manual test"],"authentication":"Personal Access Token (PAT) via the TestDino API credential; requires a public-api-scoped token that also identifies the bound project automatically","commonUseCases":["Send alerts when a TestDino test run fails","Generate scheduled quality or analytics PDF reports","Monitor usage or release health in automated workflows"],"limitations":["Requires a publicly reachable production webhook URL for trigger events","Trigger workflows only work when the workflow is active","Finished-run trigger filtering applies only server-side by the selected outcome"],"relatedNodes":["AI Agent","Schedule Trigger","IF","Slack","Gmail"]}


node_type: n8n-nodes-k2think.k2Think
package_name: n8n-nodes-k2think
display_name: K2 Think
description: Call the K2 Think V2 reasoning model (MBZUAI-IFM)
category: Community
development_style: declarative
version: 1
properties_schema: []
operations: []
credentials_required: []
outputs:
  [
  "main"
  ]

updated_at: 2026-07-14 14:40:34
author_name: iayazedan
author_github_url: https://github.com/iayazedan/
npm_package_name: n8n-nodes-k2think
npm_version: 0.1.5
community_fetched_at: 2026-07-14T14:40:34.482Z
ai_summary_generated_at: 2026-06-26 10:29:17
npm_readme:
  # n8n-nodes-k2think

  An [n8n](https://n8n.io) community node for **K2 Think V2** (MBZUAI-IFM) — the reasoning model served from the OpenAI-compatible gateway at `api.k2think.ai`.

  This is an **action node**: drop it into any workflow to send a prompt to K2 Think and get the answer back. It handles the gateway's quirks for you:

  - uses `max_completion_tokens` (not `max_tokens`)
  - non-streaming
  - automatically strips the `<think>…</think>` reasoning preamble (toggleable)
  - adds token headroom so the reasoning never truncates the answer

  > **Note on the AI Agent node:** n8n's "Chat Model" sub-nodes (the kind that plug into the AI Agent / Chains) are built on LangChain, which requires a runtime dependency and therefore cannot be verified for n8n Cloud. This package is a dependency-free action node so it *can* be verified and installed on Cloud. To use K2 Think as an Agent model on Cloud today, use the built-in **OpenAI Chat Model** node with a credential whose Base URL is `https://api.k2think.ai/v1`.

  ## Installation

  ### n8n Cloud / Self-hosted UI
  Settings → Community Nodes → Install → `n8n-nodes-k2think` (available after npm publish + n8n verification).

  ### Self-hosted (manual)
  ```bash
  cd ~/.n8n/nodes
  npm install n8n-nodes-k2think
  ```

  ## Credentials

  Create a **K2 Think API** credential:
  - **API Key** — your `api.k2think.ai` key
  - **Base URL** — defaults to `https://api.k2think.ai/v1`

  ## Usage

  Add the **K2 Think** node, pick the credential, set:
  - **Model** — `MBZUAI-IFM/K2-Think-v2`
  - **Prompt** — your user message
  - **System Prompt** (optional)
  - **Options** — temperature, max completion tokens, reasoning headroom, strip `<think>`, output field, include raw

  ## License

  MIT

ai_documentation_summary:
  {"purpose":"An n8n action node for sending prompts to the K2 Think V2 reasoning model (MBZUAI-IFM) via the OpenAI-compatible gateway at api.k2think.ai. It returns the model's answer and handles gateway-specific behavior like token settings and optional stripping of reasoning text.","capabilities":["Send a prompt to K2 Think V2 and receive a completion","Set an optional system prompt","Configure temperature","Configure max completion tokens","Add reasoning token headroom to reduce truncation","Strip the  reasoning preamble optionally","Choose the output field","Include raw response data optionally","Use an OpenAI-compatible base URL"],"authentication":"API key required via a K2 Think API credential, with an optional Base URL (defaults to https://api.k2think.ai/v1).","commonUseCases":["General reasoning and answer generation from prompts","Using K2 Think V2 in workflows for AI-assisted text generation","Calling K2 Think as an OpenAI-compatible model in n8n Cloud or self-hosted workflows"],"limitations":["Non-streaming only","This is an action node, not a LangChain Chat Model sub-node for AI Agent/Chains","To use it with AI Agent on Cloud, the README recommends the built-in OpenAI Chat Model node instead"],"relatedNodes":["OpenAI Chat Model","AI Agent"]}


node_type: n8n-nodes-truthscan.truthscan
package_name: n8n-nodes-truthscan
display_name: Truthscan
description: Detect AI-generated content with Truthscan
category: Community
development_style: declarative
version: 1
credentials_required: []
outputs:
  [
  "main",
  "main",
  "main"
  ]

updated_at: 2026-07-14 14:40:34
author_name: truthscan-com
author_github_url: https://github.com/truthscan/
npm_package_name: n8n-nodes-truthscan
npm_version: 0.1.2
community_fetched_at: 2026-07-14T14:40:34.482Z
ai_summary_generated_at: 2026-06-26 10:29:17
properties_schema:
  [
    {
      "name": "resource",
      "type": "options",
      "default": "text",
      "options": [
        {
          "name": "Image",
          "value": "image",
          "description": "Detect AI-generated images"
        },
        {
          "name": "Text",
          "value": "text",
          "description": "Detect AI-generated text"
        }
      ],
      "displayName": "Resource",
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "detect",
      "options": [
        {
          "name": "Detect",
          "value": "detect",
          "action": "Detect text",
          "description": "Submit text for AI detection and wait for the scored result. At least 200 words are recommended for best accuracy."
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "text"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "detect",
      "options": [
        {
          "name": "Detect",
          "value": "detect",
          "action": "Detect image",
          "description": "Upload an image and wait for the scored AI-detection result. Supports JPG, PNG, WebP, HEIC, HEIF, AVIF, BMP, TIFF, GIF, SVG, and PDF (max 10 MB)."
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "image"
          ]
        }
      },
      "noDataExpression": true
    }
  ]

operations:
  [
    {
      "name": "Detect",
      "value": "detect",
      "action": "Detect text",
      "description": "Submit text for AI detection and wait for the scored result. At least 200 words are recommended for best accuracy.",
      "resource": "text"
    },
    {
      "name": "Detect",
      "value": "detect",
      "action": "Detect image",
      "description": "Upload an image and wait for the scored AI-detection result. Supports JPG, PNG, WebP, HEIC, HEIF, AVIF, BMP, TIFF, GIF, SVG, and PDF (max 10 MB).",
      "resource": "image"
    }
  ]

npm_readme:
  # n8n-nodes-truthscan

  This is an n8n community node. It lets you use [Truthscan](https://truthscan.com) AI detection in your n8n workflows.

  Truthscan detects AI-generated content. This package currently ships **AI text detection** and **AI image detection**, with video and audio detection planned for future releases.

  [n8n](https://n8n.io/) is a [fair-code licensed](https://docs.n8n.io/reference/license/) workflow automation platform.

  [Installation](#installation)
  [Operations](#operations)
  [Credentials](#credentials)
  [Usage](#usage)
  [Resources](#resources)

  ## Installation

  Follow the [installation guide](https://docs.n8n.io/integrations/community-nodes/installation/) in the n8n community nodes documentation.

  In short: go to **Settings > Community Nodes**, select **Install**, and enter `n8n-nodes-truthscan`.

  ## Operations

  ### Text

  - **Detect** - Submit text for AI detection. The node calls Truthscan's `/detect` endpoint, then automatically polls `/query` until the result is ready, returning the final score in a single step. At least 200 words are recommended for best accuracy (maximum 30,000 words).

  ### Image

  - **Detect** - Submit an image for AI detection. Connect a node that outputs binary data (e.g. **HTTP Request**, **Read/Write Files from Disk**, or **Google Drive**) and point the **Input Binary Field** at it. The node runs the full 3-step Truthscan flow automatically — it requests a presigned upload URL, uploads the image to storage, submits it to `/detect`, and polls `/query` until the score is ready. Supported formats: JPG, JPEG, PNG, WebP, JFIF, HEIC, HEIF, AVIF, BMP, TIFF, TIF, GIF, SVG, and PDF (PDF analyzes the first image only). File size: 1 KB–10 MB.

  > Video and Audio detection operations are planned for future versions.

  ## Credentials

  You need a Truthscan API key.

  1. Sign up at [truthscan.com](https://truthscan.com).
  2. Open the developer portal and copy your API key.
  3. In n8n, create a new **Truthscan API** credential and paste the key.

  The credential is validated against Truthscan's `check-user-credits` endpoint when you save it.

  ## Usage

  Add the **Truthscan** node, choose a resource and the **Detect** operation. For **Text**, provide the text to analyze. For **Image**, set the **Input Binary Field** to the name of the binary property holding your image (usually `data`).

  ### Text options

  - **Generate Analysis Details** - run a deep AI analysis (agreement, confidence, key indicators, reasoning, linguistic patterns, recommendations). When enabled, the node automatically keeps polling until the analysis finishes, so the result includes `analysis_results`.
  - **Model** - detection model to use (default `xlm_ud_detector`).
  - **Retry Count** - number of retries if processing fails.
  - **Poll Interval (Ms)** - how long to wait between status checks (default 2000 ms).
  - **Max Poll Attempts** - maximum number of status checks before giving up (default 30). If the core score is ready but the analysis is still processing when this budget runs out, the node returns the completed score rather than erroring.

  ### Image options

  - **Generate Analysis Details** - run a deep AI analysis (image tags, agreement, confidence, key indicators, reasoning, visual patterns, recommendations). When enabled, the node automatically keeps polling until the analysis finishes, so the result includes `analysis_results`.
  - **Generate Preview** - generate a preview image URL (default on).
  - **Generate Heatmap** - generate a heatmap of AI-generated regions, only produced for AI-classified images (default on).
  - **Heatmap Overlayed** - blend the heatmap onto the original image; when off, returns a transparent RGBA heatmap (only when Generate Heatmap is on).
  - **Heatmap Normalized** - normalize the heatmap activation map (only when Generate Heatmap is on).
  - **Model** - model or routing hint (default `generic`).
  - **Presigned URL Expiration (Seconds)** - lifetime of the upload URL (default 3600).
  - **Storage Base URL** - override the storage host used to build the detection URL (leave empty for the default production bucket).
  - **Poll Interval (Ms)** / **Max Poll Attempts** - polling cadence and budget (defaults 2000 ms / 30). If the core score is ready but the heatmap/analysis is still processing when the budget runs out, the node returns the completed score rather than erroring.
  - **Wait for Heatmap** - keep polling until the heatmap finishes generating (only relevant when Generate Heatmap is on and the image is AI-classified).

  ### Outputs

  The node has **three outputs** so you can branch your workflow on the verdict without an extra IF/Switch node:

  | Output | Receives |
  | --- | --- |
  | **AI** | Items classified as AI-generated (score ≥ 50, or a non-`Human` text label), enriched with a `classification` object. |
  | **Real** | Items classified as authentic/human (score < 50, or the `Human` text label), enriched with a `classification` object. |
  | **Raw Output** | **Every** processed item with the unmodified Truthscan response. When *Continue On Fail* is on, error items are emitted here too. |

  The `classification` object added to the **AI** and **Real** outputs looks like:

  ```json
  {
    "classification": "AI",
    "isAI": true,
    "score": 90.24,
    "label": "Synthetic (AI)",
    "tier": "SYNTHETIC"
  }
  ```

  **Image score tiers** (`tier`/`label`), based on the 0–100 `result` score:

  | Score | Tier | Label | Routed to |
  | --- | --- | --- | --- |
  | 0–20 | `REAL` | Real | Real |
  | 20–50 | `LIKELY_REAL` | Likely Real | Real |
  | 50–80 | `LIKELY_SYNTHETIC` | Likely Synthetic (AI) | AI |
  | 80–100 | `SYNTHETIC` | Synthetic (AI) | AI |

  For **text**, the API `label` (`Human` / `AI` / `Paraphrase`) drives routing: `Human` → **Real**, everything else → **AI** (falling back to the score when no label is present). `tier` is omitted for text.

  ### Result interpretation

  The node returns the full Truthscan response. Key fields:

  - `result` - score from 0-100. Under 50 = human, 50-60 = possible AI, over 60 = AI.
  - `label` - `Human`, `AI`, or `Paraphrase`.
  - `result_details` - approximate scores from third-party detectors and (when requested) deep `analysis_results`.
  - `result_categories` - `advanced` and `standard` tiered scores.

  ### Example output

  ```json
  {
    "id": "77565038-9e3d-4e6a-8c80-e20785be5ee9",
    "model": "xlm_ud_detector",
    "result": 12.0,
    "label": "Human",
    "status": "done",
    "result_details": {
      "scoreGptZero": 50.0,
      "human": 88.0
    },
    "result_categories": { "advanced": 12, "standard": 12 }
  }
  ```

  For an **image** detection, the response includes `result` (0–100 score), `result_details.final_result` (e.g. `AI Generated`, `Real`, `Digitally Edited`), `result_details.confidence`, and — when requested and applicable — `result_details.heatmap_url`, `result_details.analysis_results`, and `preview_url`.

  ```json
  {
    "id": "00fee5ff-a55b-42fb-b7c7-d14f05ae0769",
    "status": "done",
    "result": 90.24,
    "result_details": {
      "is_valid": true,
      "detection_step": 3,
      "final_result": "AI Generated",
      "confidence": 90.24,
      "heatmap_status": "ready",
      "heatmap_url": "https://.../uploads/...",
      "analysis_results_status": "ready",
      "analysis_results": null
    },
    "preview_url": "https://.../previews/..."
  }
  ```

  ## Resources

  - [n8n community nodes documentation](https://docs.n8n.io/integrations/community-nodes/)
  - [Truthscan AI Text Detection API documentation](https://truthscan.com/truthscan-ai-text-detection-api-documentation)
  - [Truthscan AI Image Detection API documentation](https://truthscan.com/truthscan-ai-image-detection-api-documentation)

  ## License

  [MIT](LICENSE.md)

ai_documentation_summary:
  {"purpose":"Detects AI-generated content using Truthscan in n8n workflows. It supports both text and image analysis, automatically polling until a final verdict is available.","capabilities":["Text AI detection via the /detect endpoint with automatic polling of /query for final results","Image AI detection using binary input, including presigned upload, storage upload, /detect submission, and /query polling","Optional deep analysis details for text and images (analysis_results)","Optional image preview generation","Optional AI heatmap generation for images, including overlayed or transparent output","Automatic branching into AI, Real, and Raw Output streams based on classification","Configurable model selection, polling interval, retry count, and max poll attempts"],"authentication":"API key required (Truthscan API key via n8n 'Truthscan API' credential)","commonUseCases":["Flag AI-generated text before publishing or processing content","Screen uploaded images for AI-generated or synthetic content","Route suspicious content to manual review while allowing human-authored content to continue"],"limitations":["Video and audio detection are not yet available; they are planned for future releases","Text detection recommends at least 200 words and has a maximum input size of 30,000 words","Image detection supports files from 1 KB to 10 MB only","PDF image detection analyzes only the first image in the PDF"],"relatedNodes":["HTTP Request","Read/Write Files from Disk","Google Drive","IF","Switch"]}


node_type: n8n-nodes-polydoc.polyDoc
package_name: n8n-nodes-polydoc
display_name: PolyDoc
description: Convert HTML or URLs to PDF, capture screenshots, and generate EU e-invoices
category: Community
development_style: declarative
version: 1
credentials_required: []
outputs:
  [
  "main"
  ]

updated_at: 2026-07-14 14:40:34
author_name: polydoc.tech
author_github_url: https://github.com/polydoc-tech/
npm_package_name: n8n-nodes-polydoc
npm_version: 0.1.6
community_fetched_at: 2026-07-14T14:40:34.483Z
ai_summary_generated_at: 2026-06-26 10:29:17
properties_schema:
  [
    {
      "name": "operation",
      "type": "options",
      "default": "pdf",
      "options": [
        {
          "name": "HTML/URL to PDF",
          "value": "pdf",
          "action": "Convert HTML or a URL to PDF"
        },
        {
          "name": "Capture Screenshot",
          "value": "screenshot",
          "action": "Capture a screenshot of HTML or a URL"
        },
        {
          "name": "Generate E-Invoice",
          "value": "einvoice",
          "action": "Generate an electronic invoice"
        }
      ],
      "displayName": "Operation",
      "noDataExpression": true
    }
  ]

operations:
  [
    {
      "name": "HTML/URL to PDF",
      "value": "pdf",
      "action": "Convert HTML or a URL to PDF"
    },
    {
      "name": "Capture Screenshot",
      "value": "screenshot",
      "action": "Capture a screenshot of HTML or a URL"
    },
    {
      "name": "Generate E-Invoice",
      "value": "einvoice",
      "action": "Generate an electronic invoice"
    }
  ]

npm_readme:
  # n8n-nodes-polydoc

  An [n8n](https://n8n.io) community node for [PolyDoc](https://polydoc.tech) - a REST API that converts HTML or URLs to **PDF**, captures **screenshots**, and generates EU-compliant **e-invoices** (Factur-X / ZUGFeRD hybrid PDF/A-3).

  One node, three operations:

  - **HTML/URL to PDF** - layout, margins, page format, page ranges, bookmarks, accessible/tagged PDFs.
  - **Capture Screenshot** - PNG / JPEG / WebP, full page, viewport and device-pixel-ratio control.
  - **Generate E-Invoice** - Factur-X or ZUGFeRD, profiles from `minimum` to `extended`.

  Content can come from a **URL**, an inline **HTML** string, or a saved **template** (with Liquid `templateData`). The result is returned as binary data by default, or uploaded to your **cloud storage** (presigned URL) or delivered to a **webhook**.

  ## Installation

  In n8n: **Settings → Community Nodes → Install**, then enter `n8n-nodes-polydoc`.

  Self-hosted (manual):

  ```bash
  npm install n8n-nodes-polydoc
  ```

  ## Credentials

  Create a **PolyDoc API** credential with an API key from [dashboard.polydoc.tech](https://dashboard.polydoc.tech) (API Keys). Toggle **Sandbox** to test with sandbox quota (watermarked output). The key is sent as `Authorization: Bearer <key>`.

  ## Anything not in the UI?

  Every operation has an **Additional Fields → Advanced (JSON)** escape hatch that is deep-merged into the request body, so any API capability not surfaced as a control (e.g. `pdf.watermark`, `pdf.pdfa`, `pdf.encryption`, `render.*`, `request.*`) is still reachable. See the full request schema at [docs.polydoc.tech](https://docs.polydoc.tech).

  ## Development

  ```bash
  npm install
  npm run build      # tsc + copy icons into dist/
  npm run lint       # eslint-plugin-n8n-nodes-base
  npm test           # unit tests (request body builder)
  ```

  Live smoke test against the real API (uses sandbox quota):

  ```bash
  POLYDOC_API_KEY=api_xxx POLYDOC_TEMPLATE_ID=jlE-whg npm run test:integration
  ```

  ## License

  [MIT](./LICENSE)

ai_documentation_summary:
  {"purpose":"PolyDoc is an n8n community node that converts HTML or URLs into PDFs, captures webpage screenshots, and generates EU-compliant e-invoices. It can also use saved templates with Liquid data to produce outputs.","capabilities":["Convert HTML or URLs to PDF","Configure PDF layout, margins, page format, page ranges, bookmarks, and accessible/tagged PDFs","Capture screenshots as PNG, JPEG, or WebP","Capture full-page screenshots and control viewport/device pixel ratio","Generate EU e-invoices in Factur-X or ZUGFeRD format","Support invoice profiles from minimum to extended","Use content from a URL, inline HTML, or a saved template with Liquid templateData","Return results as binary data, upload to cloud storage via presigned URL, or deliver to a webhook","Expose advanced JSON fields for API options not shown in the UI, such as watermarking, PDF/A, encryption, render settings, and request settings"],"authentication":"API key required via PolyDoc API credential; the key is sent as Authorization: Bearer <key>. Sandbox mode is available for testing with sandbox quota and watermarked output.","commonUseCases":["Generate PDFs from web pages or HTML content in automated workflows","Take webpage screenshots for reports, monitoring, or archiving","Create EU-compliant electronic invoices from workflow data","Produce branded documents from reusable templates and dynamic data"],"limitations":["Advanced API features may require using the Additional Fields → Advanced (JSON) escape hatch because not every option is exposed in the UI","Sandbox mode uses quota and produces watermarked output"],"relatedNodes":[]}


node_type: n8n-nodes-encelade.enceladeTrigger
package_name: n8n-nodes-encelade
display_name: Encelade Trigger
description: Starts the workflow when an Encelade generation completes or fails
category: Community
development_style: declarative
version: 1
properties_schema: []
operations: []
credentials_required: []
outputs:
  [
  "main"
  ]

updated_at: 2026-07-14 14:40:34
author_name: spl1n
author_github_url: https://github.com/encelade-ai/
npm_package_name: n8n-nodes-encelade
npm_version: 0.1.5
community_fetched_at: 2026-07-14T14:40:34.484Z
ai_summary_generated_at: 2026-06-26 10:29:17
npm_readme:
  # n8n-nodes-encelade

  This is an n8n community node. It lets you use [Encelade](https://www.encelade.ai) in your n8n workflows.

  Encelade turns a prompt and a few hints into a fully designed, on-brand presentation. This package wraps the Encelade public API so you can plan outlines, generate decks, manage presentations, and react to generation events — all from n8n.

  [n8n](https://n8n.io/) is a [fair-code licensed](https://docs.n8n.io/sustainable-use-license/) workflow automation platform.

  [Installation](#installation)
  [Operations](#operations)
  [Credentials](#credentials)
  [Compatibility](#compatibility)
  [Usage](#usage)
  [Resources](#resources)

  ## Installation

  Follow the [installation guide](https://docs.n8n.io/integrations/community-nodes/installation/) in the n8n community nodes documentation.

  In short: in your n8n instance go to **Settings → Community Nodes → Install**, enter `n8n-nodes-encelade`, and confirm. After installation you will have two nodes available: **Encelade** (actions) and **Encelade Trigger** (events).

  A ready-to-import example workflow lives in **[`examples/generate-deck.json`](examples/generate-deck.json)** — it generates a deck from a prompt and polls until it's ready. Import it (n8n → **⋯ → Import from File**), select your Encelade API credential on the two Encelade nodes, and run.

  ## Operations

  ### Encelade (action node)

  **Presentation**

  | Operation          | Description                                                                | API                                               |
  | ------------------ | -------------------------------------------------------------------------- | ------------------------------------------------- |
  | Generate           | Plan and generate a deck in one async call. Returns a `sessionId` to poll. | `POST /api/public/v1/projects/generate`           |
  | Plan Outline       | Generate an editable outline (synchronous by default).                     | `POST /api/public/v1/projects/plan`               |
  | Generate From Plan | Build a deck from an existing/edited plan. Async by default.               | `POST /api/public/v1/projects/generate-from-plan` |
  | Get                | Retrieve a presentation by ID.                                             | `GET /api/public/v1/projects/{id}`                |
  | Get Many           | List presentations (supports Return All).                                  | `GET /api/public/v1/projects`                     |
  | Get Published      | Retrieve a published deck by its public slug.                              | `GET /api/public/published/{slug}`                |
  | Update             | Update presentation settings.                                              | `PATCH /api/public/v1/projects/{id}`              |
  | Delete             | Delete a presentation.                                                     | `DELETE /api/public/v1/projects/{id}`             |

  **Session**

  | Operation  | Description                                  | API                                          |
  | ---------- | -------------------------------------------- | -------------------------------------------- |
  | Get Status | Poll a generation session for status/result. | `GET /api/public/v1/sessions/{sessionId}`    |
  | Cancel     | Cancel an in-progress generation.            | `DELETE /api/public/v1/sessions/{sessionId}` |

  The **Generate** and **Plan Outline** operations both expose **Topic**, **Outline Hints** (required) and **Page Count** up front. Everything else — Tone, Audience, Image Style, Verbosity, Model, Theme, Theme Mode, Media Provider, Icon Family, Call To Action (text + toggle), Deep Research, Use Connectors, End-User Email/Role, Callback URL — lives under **Additional Fields**, plus a **Supporting Materials** collection.

  > **Polling is not handled inside the node.** `Generate` returns a `sessionId` immediately; you decide how to wait (a Wait node + Get Status loop, or the Encelade Trigger node). This keeps long-running generations from tying up an n8n worker.

  ### Encelade Trigger (trigger node)

  Starts a workflow when a generation finishes. On activation it registers a webhook with Encelade (`POST /api/public/v1/webhooks`) using the node's webhook URL and a generated secret; on deactivation it removes it. Inbound calls are verified against the `X-Webhook-Signature` HMAC-SHA256 header, so unsigned/forged requests are rejected.

  - **Generation Completed** (`generation.completed`)
  - **Generation Failed** (`generation.failed`)

  ## Credentials

  You need an Encelade API token.

  1. Get a token the quick way at **[encelade.ai/setup/n8n](https://www.encelade.ai/setup/n8n)** — sign in and click **Mint** (it provisions your account if needed). Or create one manually in your Encelade account / API settings.
  2. Grant the scopes your workflow needs (each operation needs only the scopes listed):
     - `project:plan` — Plan Outline
     - `project:plan` + `project:generate` — Generate (it plans _then_ generates, so it needs both)
     - `project:generate` — Generate From Plan
     - `project:read` — Get / Get Many (also the credential Test button)
     - `project:write` — Update
     - `project:delete` — Delete
     - `session:read` — Get Status
     - `session:write` — Cancel
     - `webhook:read` + `webhook:write` — Encelade Trigger
  3. In n8n create **Encelade API** credentials and paste the token into **API Key**. The token is sent as `Authorization: Bearer <token>` and the tenant is derived from the token — no extra header needed.
  4. **Base URL** defaults to `https://www.encelade.ai`; change it only for self-hosted deployments.

  Use the credential's **Test** button to verify the token (it calls `GET /api/public/v1/projects?limit=1`).

  > The Test button needs the `project:read` scope, since that is the endpoint it probes. Full-access tokens (OAuth-minted or legacy tokens with no scope restriction) and any token that includes `project:read` pass it. A narrowly-scoped token without `project:read` (for example a generate-only or webhook-only token) is still valid and will work in its operations, but the Test button will report a 403 — add `project:read` if you want it to pass.

  ## Compatibility

  Built and tested against n8n with `n8n-workflow` 2.x (n8n nodes API version 1). Requires Node.js 20+.

  ## Usage

  ### Generate → Poll (recommended)

  **Generate** plans _and_ builds the deck in a single call — there is no separate plan step to run first. Planning happens inside the operation, which is why the initial response reads `status: "planning"`. It returns a `sessionId` immediately; you then poll for the result:

  1. **Encelade → Generate** with a Topic and at least one Outline Hint → returns `{ sessionId, status: "planning" }`.
  2. **Wait** node (e.g. 15–30s).
  3. **Encelade → Session: Get Status** with the `sessionId`.
  4. **IF** `phase` is `done` → continue (the response includes `projectPid` and `link`; `shareLink` is present only when the deck was generated for an end user via End-User Email). If `phase` is `failed` → handle the error. Otherwise loop back to the Wait node.
  5. Optionally **Encelade → Get** or **Get Published** to fetch the finished deck.

  ### Review the outline first (optional)

  Use this only when a human (or another workflow step) needs to review or edit the outline before slides are built. Note that **Generate ignores a plan** — to build from an edited outline you must use **Generate From Plan**, not Generate:

  1. **Encelade → Plan Outline** with a Topic and Outline Hints → returns an editable `plan`.
  2. Edit the `plan` as needed (e.g. a Set/Edit Fields node or a manual approval step).
  3. **Encelade → Generate From Plan** with that plan → returns a `sessionId`.
  4. Poll **Session → Get Status** as in steps 2–5 above.

  ### Event-driven (no polling)

  Instead of polling, add an **Encelade Trigger** node, subscribe to **Generation Completed** / **Generation Failed**, and activate the workflow before generating. The trigger fires with `{ event, sessionId, projectPid, timestamp }` when the deck is ready.

  > Generation typically takes up to ~3 minutes for a 10–15 page deck (longer with Deep Research).

  ## Resources

  - [n8n community nodes documentation](https://docs.n8n.io/integrations/#community-nodes)
  - [Encelade](https://www.encelade.ai)

ai_documentation_summary:
  {"purpose":"Encelade nodes let you automate presentation generation workflows in n8n using the Encelade public API. The action node manages planning, generating, and administering presentations, while the trigger node starts workflows when generation events complete or fail.","capabilities":["Generate a presentation deck from a prompt and hints (returns a sessionId for async completion)","Plan an editable outline before generation","Generate a deck from an existing or edited plan","Retrieve presentations by ID or public slug","List presentations with support for returning all results","Update presentation settings","Delete presentations","Poll generation session status and results","Cancel in-progress generation sessions","Trigger workflows on generation.completed events"],"authentication":"Encelade API token required; token is sent as Authorization: Bearer <token> using n8n Encelade API credentials. The trigger also registers/removes webhooks and verifies inbound requests using an HMAC-SHA256 X-Webhook-Signature.","commonUseCases":["Automatically generate branded slide decks from prompts","Create outlines, edit them in n8n, then generate final presentations","Track long-running generation jobs with polling or a webhook trigger","Manage presentation records such as fetching, updating, or deleting decks","React to successful or failed generation events in downstream workflows"],"limitations":["Polling is not handled inside the node; users must implement waiting/polling externally or use the trigger node","Generate and Plan Outline require required inputs upfront, with most other options only available under Additional Fields","The trigger only supports generation completed and generation failed events"],"relatedNodes":["Encelade","Wait"]}


node_type: n8n-nodes-encelade.encelade
package_name: n8n-nodes-encelade
display_name: Encelade
description: Generate and manage AI presentations with the Encelade API
category: Community
development_style: declarative
version: 1
credentials_required: []
outputs:
  [
  "main"
  ]

updated_at: 2026-07-14 14:40:34
author_name: spl1n
author_github_url: https://github.com/encelade-ai/
npm_package_name: n8n-nodes-encelade
npm_version: 0.1.5
community_fetched_at: 2026-07-14T14:40:34.485Z
ai_summary_generated_at: 2026-06-26 10:29:17
properties_schema:
  [
    {
      "name": "resource",
      "type": "options",
      "default": "presentation",
      "options": [
        {
          "name": "Presentation",
          "value": "presentation"
        },
        {
          "name": "Session",
          "value": "session"
        }
      ],
      "displayName": "Resource",
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "generate",
      "options": [
        {
          "name": "Delete",
          "value": "delete",
          "action": "Delete a presentation",
          "description": "Delete a presentation"
        },
        {
          "name": "Generate",
          "value": "generate",
          "action": "Generate a presentation",
          "description": "Plan and generate a presentation in one asynchronous call"
        },
        {
          "name": "Generate From Plan",
          "value": "generateFromPlan",
          "action": "Generate a presentation from a plan",
          "description": "Build a presentation from an existing or edited plan"
        },
        {
          "name": "Get",
          "value": "get",
          "action": "Get a presentation",
          "description": "Retrieve a single presentation by ID"
        },
        {
          "name": "Get Many",
          "value": "getAll",
          "action": "Get many presentations",
          "description": "List presentations"
        },
        {
          "name": "Get Published",
          "value": "getPublished",
          "action": "Get a published presentation",
          "description": "Retrieve a published presentation by its public slug (no token required)"
        },
        {
          "name": "Plan Outline",
          "value": "plan",
          "action": "Plan a presentation outline",
          "description": "Generate an editable outline without building slides"
        },
        {
          "name": "Update",
          "value": "update",
          "action": "Update a presentation",
          "description": "Update presentation settings"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "presentation"
          ]
        }
      },
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "getStatus",
      "options": [
        {
          "name": "Cancel",
          "value": "cancel",
          "action": "Cancel a generation",
          "description": "Cancel an in-progress generation session"
        },
        {
          "name": "Get Status",
          "value": "getStatus",
          "action": "Get generation status",
          "description": "Poll a generation session for its status and result"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "session"
          ]
        }
      },
      "noDataExpression": true
    }
  ]

operations:
  [
    {
      "name": "Delete",
      "value": "delete",
      "action": "Delete a presentation",
      "description": "Delete a presentation",
      "resource": "presentation"
    },
    {
      "name": "Generate",
      "value": "generate",
      "action": "Generate a presentation",
      "description": "Plan and generate a presentation in one asynchronous call",
      "resource": "presentation"
    },
    {
      "name": "Generate From Plan",
      "value": "generateFromPlan",
      "action": "Generate a presentation from a plan",
      "description": "Build a presentation from an existing or edited plan",
      "resource": "presentation"
    },
    {
      "name": "Get",
      "value": "get",
      "action": "Get a presentation",
      "description": "Retrieve a single presentation by ID",
      "resource": "presentation"
    },
    {
      "name": "Get Many",
      "value": "getAll",
      "action": "Get many presentations",
      "description": "List presentations",
      "resource": "presentation"
    },
    {
      "name": "Get Published",
      "value": "getPublished",
      "action": "Get a published presentation",
      "description": "Retrieve a published presentation by its public slug (no token required)",
      "resource": "presentation"
    },
    {
      "name": "Plan Outline",
      "value": "plan",
      "action": "Plan a presentation outline",
      "description": "Generate an editable outline without building slides",
      "resource": "presentation"
    },
    {
      "name": "Update",
      "value": "update",
      "action": "Update a presentation",
      "description": "Update presentation settings",
      "resource": "presentation"
    },
    {
      "name": "Cancel",
      "value": "cancel",
      "action": "Cancel a generation",
      "description": "Cancel an in-progress generation session",
      "resource": "session"
    },
    {
      "name": "Get Status",
      "value": "getStatus",
      "action": "Get generation status",
      "description": "Poll a generation session for its status and result",
      "resource": "session"
    }
  ]

npm_readme:
  # n8n-nodes-encelade

  This is an n8n community node. It lets you use [Encelade](https://www.encelade.ai) in your n8n workflows.

  Encelade turns a prompt and a few hints into a fully designed, on-brand presentation. This package wraps the Encelade public API so you can plan outlines, generate decks, manage presentations, and react to generation events — all from n8n.

  [n8n](https://n8n.io/) is a [fair-code licensed](https://docs.n8n.io/sustainable-use-license/) workflow automation platform.

  [Installation](#installation)
  [Operations](#operations)
  [Credentials](#credentials)
  [Compatibility](#compatibility)
  [Usage](#usage)
  [Resources](#resources)

  ## Installation

  Follow the [installation guide](https://docs.n8n.io/integrations/community-nodes/installation/) in the n8n community nodes documentation.

  In short: in your n8n instance go to **Settings → Community Nodes → Install**, enter `n8n-nodes-encelade`, and confirm. After installation you will have two nodes available: **Encelade** (actions) and **Encelade Trigger** (events).

  A ready-to-import example workflow lives in **[`examples/generate-deck.json`](examples/generate-deck.json)** — it generates a deck from a prompt and polls until it's ready. Import it (n8n → **⋯ → Import from File**), select your Encelade API credential on the two Encelade nodes, and run.

  ## Operations

  ### Encelade (action node)

  **Presentation**

  | Operation          | Description                                                                | API                                               |
  | ------------------ | -------------------------------------------------------------------------- | ------------------------------------------------- |
  | Generate           | Plan and generate a deck in one async call. Returns a `sessionId` to poll. | `POST /api/public/v1/projects/generate`           |
  | Plan Outline       | Generate an editable outline (synchronous by default).                     | `POST /api/public/v1/projects/plan`               |
  | Generate From Plan | Build a deck from an existing/edited plan. Async by default.               | `POST /api/public/v1/projects/generate-from-plan` |
  | Get                | Retrieve a presentation by ID.                                             | `GET /api/public/v1/projects/{id}`                |
  | Get Many           | List presentations (supports Return All).                                  | `GET /api/public/v1/projects`                     |
  | Get Published      | Retrieve a published deck by its public slug.                              | `GET /api/public/published/{slug}`                |
  | Update             | Update presentation settings.                                              | `PATCH /api/public/v1/projects/{id}`              |
  | Delete             | Delete a presentation.                                                     | `DELETE /api/public/v1/projects/{id}`             |

  **Session**

  | Operation  | Description                                  | API                                          |
  | ---------- | -------------------------------------------- | -------------------------------------------- |
  | Get Status | Poll a generation session for status/result. | `GET /api/public/v1/sessions/{sessionId}`    |
  | Cancel     | Cancel an in-progress generation.            | `DELETE /api/public/v1/sessions/{sessionId}` |

  The **Generate** and **Plan Outline** operations both expose **Topic**, **Outline Hints** (required) and **Page Count** up front. Everything else — Tone, Audience, Image Style, Verbosity, Model, Theme, Theme Mode, Media Provider, Icon Family, Call To Action (text + toggle), Deep Research, Use Connectors, End-User Email/Role, Callback URL — lives under **Additional Fields**, plus a **Supporting Materials** collection.

  > **Polling is not handled inside the node.** `Generate` returns a `sessionId` immediately; you decide how to wait (a Wait node + Get Status loop, or the Encelade Trigger node). This keeps long-running generations from tying up an n8n worker.

  ### Encelade Trigger (trigger node)

  Starts a workflow when a generation finishes. On activation it registers a webhook with Encelade (`POST /api/public/v1/webhooks`) using the node's webhook URL and a generated secret; on deactivation it removes it. Inbound calls are verified against the `X-Webhook-Signature` HMAC-SHA256 header, so unsigned/forged requests are rejected.

  - **Generation Completed** (`generation.completed`)
  - **Generation Failed** (`generation.failed`)

  ## Credentials

  You need an Encelade API token.

  1. Get a token the quick way at **[encelade.ai/setup/n8n](https://www.encelade.ai/setup/n8n)** — sign in and click **Mint** (it provisions your account if needed). Or create one manually in your Encelade account / API settings.
  2. Grant the scopes your workflow needs (each operation needs only the scopes listed):
     - `project:plan` — Plan Outline
     - `project:plan` + `project:generate` — Generate (it plans _then_ generates, so it needs both)
     - `project:generate` — Generate From Plan
     - `project:read` — Get / Get Many (also the credential Test button)
     - `project:write` — Update
     - `project:delete` — Delete
     - `session:read` — Get Status
     - `session:write` — Cancel
     - `webhook:read` + `webhook:write` — Encelade Trigger
  3. In n8n create **Encelade API** credentials and paste the token into **API Key**. The token is sent as `Authorization: Bearer <token>` and the tenant is derived from the token — no extra header needed.
  4. **Base URL** defaults to `https://www.encelade.ai`; change it only for self-hosted deployments.

  Use the credential's **Test** button to verify the token (it calls `GET /api/public/v1/projects?limit=1`).

  > The Test button needs the `project:read` scope, since that is the endpoint it probes. Full-access tokens (OAuth-minted or legacy tokens with no scope restriction) and any token that includes `project:read` pass it. A narrowly-scoped token without `project:read` (for example a generate-only or webhook-only token) is still valid and will work in its operations, but the Test button will report a 403 — add `project:read` if you want it to pass.

  ## Compatibility

  Built and tested against n8n with `n8n-workflow` 2.x (n8n nodes API version 1). Requires Node.js 20+.

  ## Usage

  ### Generate → Poll (recommended)

  **Generate** plans _and_ builds the deck in a single call — there is no separate plan step to run first. Planning happens inside the operation, which is why the initial response reads `status: "planning"`. It returns a `sessionId` immediately; you then poll for the result:

  1. **Encelade → Generate** with a Topic and at least one Outline Hint → returns `{ sessionId, status: "planning" }`.
  2. **Wait** node (e.g. 15–30s).
  3. **Encelade → Session: Get Status** with the `sessionId`.
  4. **IF** `phase` is `done` → continue (the response includes `projectPid` and `link`; `shareLink` is present only when the deck was generated for an end user via End-User Email). If `phase` is `failed` → handle the error. Otherwise loop back to the Wait node.
  5. Optionally **Encelade → Get** or **Get Published** to fetch the finished deck.

  ### Review the outline first (optional)

  Use this only when a human (or another workflow step) needs to review or edit the outline before slides are built. Note that **Generate ignores a plan** — to build from an edited outline you must use **Generate From Plan**, not Generate:

  1. **Encelade → Plan Outline** with a Topic and Outline Hints → returns an editable `plan`.
  2. Edit the `plan` as needed (e.g. a Set/Edit Fields node or a manual approval step).
  3. **Encelade → Generate From Plan** with that plan → returns a `sessionId`.
  4. Poll **Session → Get Status** as in steps 2–5 above.

  ### Event-driven (no polling)

  Instead of polling, add an **Encelade Trigger** node, subscribe to **Generation Completed** / **Generation Failed**, and activate the workflow before generating. The trigger fires with `{ event, sessionId, projectPid, timestamp }` when the deck is ready.

  > Generation typically takes up to ~3 minutes for a 10–15 page deck (longer with Deep Research).

  ## Resources

  - [n8n community nodes documentation](https://docs.n8n.io/integrations/#community-nodes)
  - [Encelade](https://www.encelade.ai)

ai_documentation_summary:
  {"purpose":"Encelade is an n8n node for generating, planning, and managing AI-powered presentations through the Encelade public API. It can also trigger workflows when presentation generation finishes or fails.","capabilities":["Generate a presentation deck from a prompt and hints","Plan an editable presentation outline","Generate a deck from an existing or edited plan","Retrieve a presentation by ID","List presentations with support for Return All","Retrieve a published presentation by public slug","Update presentation settings","Delete a presentation","Poll generation session status and results","Cancel an in-progress generation session"],"authentication":"API token required via Encelade API credentials; token is sent as Authorization: Bearer <token>. Specific operations require scoped permissions, and the base URL defaults to https://www.encelade.ai.","commonUseCases":["Automating AI presentation generation from a workflow prompt","Creating an outline, editing it, then generating the final deck","Polling or reacting to long-running presentation generation jobs","Managing existing presentations programmatically","Starting workflows when a presentation generation completes or fails"],"limitations":["Polling is not handled inside the Generate operation; users must implement waiting via a Wait/Get Status loop or use the trigger node","Generate and Plan Outline require Outline Hints and Page Count up front","The node depends on API scopes matching the selected operation"],"relatedNodes":["Encelade Trigger","Wait"]}


node_type: n8n-nodes-zenchef.zenchef
package_name: n8n-nodes-zenchef
display_name: Zenchef
description: Check restaurant availability via the Zenchef public widget API
category: Community
development_style: declarative
version: 1
credentials_required: []
outputs:
  [
  "main"
  ]

updated_at: 2026-07-14 14:40:34
author_name: looorent
author_github_url: https://github.com/looorent/
npm_package_name: n8n-nodes-zenchef
npm_version: 0.2.2
community_fetched_at: 2026-07-14T14:40:34.486Z
ai_summary_generated_at: 2026-06-26 10:29:17
properties_schema:
  [
    {
      "name": "operation",
      "type": "options",
      "default": "findForDateRange",
      "options": [
        {
          "name": "Find for Date Range",
          "value": "findForDateRange",
          "action": "Find availability for a date range",
          "routing": {
            "output": {
              "postReceive": [
                null,
                null
              ]
            },
            "request": {
              "url": "/getAvailabilitiesSummary",
              "method": "GET",
              "ignoreHttpStatusErrors": true
            }
          },
          "description": "Pick two dates (max ~30 days apart)"
        },
        {
          "name": "Find for Day",
          "value": "findForDay",
          "action": "Find availability for a day",
          "routing": {
            "output": {
              "postReceive": [
                null,
                null
              ]
            },
            "request": {
              "url": "/getAvailabilitiesSummary",
              "method": "GET",
              "ignoreHttpStatusErrors": true
            }
          },
          "description": "Check a single day"
        },
        {
          "name": "Find for Month",
          "value": "findForMonth",
          "action": "Find availability for a month",
          "routing": {
            "output": {
              "postReceive": [
                null,
                null
              ]
            },
            "request": {
              "url": "/getAvailabilitiesSummary",
              "method": "GET",
              "ignoreHttpStatusErrors": true
            }
          },
          "description": "Get the full calendar for a given month"
        },
        {
          "name": "Find for Upcoming Days",
          "value": "findForUpcomingDays",
          "action": "Find availability for upcoming days",
          "routing": {
            "output": {
              "postReceive": [
                null,
                null
              ]
            },
            "request": {
              "url": "/getAvailabilitiesSummary",
              "method": "GET",
              "ignoreHttpStatusErrors": true
            }
          },
          "description": "Check the next N days starting from today"
        }
      ],
      "displayName": "Operation",
      "noDataExpression": true
    }
  ]

operations:
  [
    {
      "name": "Find for Date Range",
      "value": "findForDateRange",
      "action": "Find availability for a date range",
      "routing": {
        "output": {
          "postReceive": [
            null,
            null
          ]
        },
        "request": {
          "url": "/getAvailabilitiesSummary",
          "method": "GET",
          "ignoreHttpStatusErrors": true
        }
      },
      "description": "Pick two dates (max ~30 days apart)"
    },
    {
      "name": "Find for Day",
      "value": "findForDay",
      "action": "Find availability for a day",
      "routing": {
        "output": {
          "postReceive": [
            null,
            null
          ]
        },
        "request": {
          "url": "/getAvailabilitiesSummary",
          "method": "GET",
          "ignoreHttpStatusErrors": true
        }
      },
      "description": "Check a single day"
    },
    {
      "name": "Find for Month",
      "value": "findForMonth",
      "action": "Find availability for a month",
      "routing": {
        "output": {
          "postReceive": [
            null,
            null
          ]
        },
        "request": {
          "url": "/getAvailabilitiesSummary",
          "method": "GET",
          "ignoreHttpStatusErrors": true
        }
      },
      "description": "Get the full calendar for a given month"
    },
    {
      "name": "Find for Upcoming Days",
      "value": "findForUpcomingDays",
      "action": "Find availability for upcoming days",
      "routing": {
        "output": {
          "postReceive": [
            null,
            null
          ]
        },
        "request": {
          "url": "/getAvailabilitiesSummary",
          "method": "GET",
          "ignoreHttpStatusErrors": true
        }
      },
      "description": "Check the next N days starting from today"
    }
  ]

npm_readme:
  # n8n-nodes-zenchef

  This is an n8n community node that lets you query restaurant **availability** from [Zenchef](https://www.zenchef.com) in your n8n workflows.

  Zenchef is a restaurant management platform widely used across Europe for reservations, guest management, and marketing. This node interacts with the **public widget API** that powers Zenchef's online booking widgets — the same endpoint any visitor hits when checking availability on a restaurant's website.

  [n8n](https://n8n.io/) is a [fair-code licensed](https://docs.n8n.io/sustainable-use-license/) workflow automation platform.

  [Installation](#installation) | [Operations](#operations) | [Credentials](#credentials) | [Usage](#usage) | [Important notice](#important-notice-regarding-the-public-api) | [Publishing](#publishing) | [Resources](#resources)

  ## Important notice regarding the public API

  This node queries the **public, unauthenticated** Zenchef bookings-middleware API (`bookings-middleware.zenchef.com`). This is the same API that Zenchef exposes through its reservation widgets embedded on restaurant websites. Please keep the following in mind:

  - **This is not the private Zenchef API.** This node does not access any private, authenticated, or partner-level endpoint. It only reads publicly available availability data — the exact same data any website visitor can see.
  - **No authentication is required or used.** Because the endpoint is public, no API key or credentials are needed. This also means there is no official rate-limiting contract or SLA.
  - **Use this node responsibly.** The absence of authentication does not mean the API is intended for heavy or automated use. Do not use this node to poll aggressively, scrape data at scale, or build services that place unreasonable load on Zenchef's infrastructure.
  - **Respect reasonable request rates.** Avoid running workflows on tight cron schedules (e.g. every few seconds). A request every few minutes for a handful of restaurants is a sensible baseline. If you need high-frequency data, contact Zenchef directly about their official integrations.
  - **This project is not affiliated with Zenchef.** It is an independent community node. Zenchef may change, restrict, or shut down this public endpoint at any time without notice. The authors of this node bear no responsibility for disruptions caused by API changes.
  - **Do not use this node for any activity that violates Zenchef's terms of service.**

  ## Installation

  Follow the [installation guide](https://docs.n8n.io/integrations/community-nodes/installation/) in the n8n community nodes documentation.

  ## Operations

  All operations query restaurant availability through the `/getAvailabilitiesSummary` endpoint.

  | Operation | Description |
  |---|---|
  | **Find for Date Range** | Pick two dates and get availability for each day in between (max ~30 days) |
  | **Find for Day** | Check a single day |
  | **Find for Month** | Get the full calendar for a given month (year + month dropdown) |
  | **Find for Upcoming Days** | Check the next N days starting from today |

  Every operation requires a **Restaurant ID** — the numeric identifier Zenchef assigns to each restaurant (see [Finding the Restaurant ID](#finding-the-restaurant-id)).

  ## Output format

  The node filters the raw API response and produces **one item per available shift per day**. Closed days and shifts without availability are excluded. Each item has this shape:

  ```json
  {
    "id": 1001,
    "name": "Lunch",
    "schedule": {
      "date": "2026-03-01",
      "dayOfWeek": 0,
      "isWeekend": true
    },
    "guestCapacity": {
      "min": 1,
      "max": 6
    },
    "bookable": {
      "from": "2025-12-01 19:00:00",
      "to": "2026-02-28 19:00:00"
    }
  }
  ```

  ### Fields

  | Field | Type | Description |
  |---|---|---|
  | `id` | `number \| null` | Unique identifier of the shift. `null` when the API omits it |
  | `name` | `string \| null` | Display name of the shift (e.g. `"Lunch"`, `"Dinner"`). `null` when the API omits it or returns an empty string |
  | `schedule.date` | `string` | The calendar date in `YYYY-MM-DD` format |
  | `schedule.dayOfWeek` | `number` | Day of the week as a number (`0` = Sunday, `6` = Saturday) |
  | `schedule.isWeekend` | `boolean` | `true` for Saturday and Sunday |
  | `guestCapacity.min` | `number` | Smallest party size accepted for this shift |
  | `guestCapacity.max` | `number` | Largest party size accepted for this shift |
  | `bookable.from` | `string \| undefined` | Start of the booking window (`YYYY-MM-DD HH:mm:ss`) |
  | `bookable.to` | `string \| undefined` | End of the booking window (`YYYY-MM-DD HH:mm:ss`) |

  ### Filtering logic

  The node applies the following filters before producing items:

  1. **Closed days** are excluded — only days with `isOpen === true` and a valid `shifts` array are kept.
  2. **Unavailable shifts** are excluded — a shift must have `closed !== true` and at least one entry in `possible_guests`.
  3. **Number of Guests** (optional) — when set via **Options > Number of Guests**, only shifts whose `possible_guests` list includes that exact party size are kept.
  4. Each remaining shift becomes its own output item.

  If no shifts pass these filters, the node throws a "No availability data returned" error.

  ## Credentials

  No credentials are required. This node uses the public Zenchef widget API, which does not require authentication.

  ## Usage

  ### Finding the Restaurant ID

  Every Zenchef restaurant has a numeric ID. To find it:

  1. Go to the restaurant's website and open the Zenchef booking widget (the "Reserve" button).
  2. Open your browser's Developer Tools (F12) and switch to the **Network** tab.
  3. Click on a date in the widget and look for a request to `bookings-middleware.zenchef.com`.
  4. The `restaurantId` query parameter in the request URL is the ID you need (e.g. `123456`).

  ### Quick start

  1. Add the **Zenchef** node to your workflow.
  2. Enter the **Restaurant ID**.
  3. Pick the operation that matches your use case (see examples below).

  ### Example workflows

  **Daily availability check** — Run on a schedule every morning to check if a restaurant has open slots this week:
  - Trigger: Schedule (every day at 8:00)
  - Zenchef: **Find for Upcoming Days**, Number of Days = `7`
  - IF: Check `{{ $json.schedule.date }}` is not empty (the node only outputs available shifts, so any output means availability exists)
  - Slack / Email: Notify with `{{ $json.schedule.date }}` and `{{ $json.name }}`

  **Check availability for a party size** — Find out which dates can seat 6 guests:
  - Zenchef: **Find for Date Range**, From = `2026-03-15`, To = `2026-03-22`, Options > Number of Guests = `6`
  - The node only outputs shifts that accept exactly 6 guests — no extra filtering needed

  **Monthly calendar overview** — Fetch the full month to build a calendar view:
  - Zenchef: **Find for Month**, Year = `2026`, Month = `March`
  - Each item is a shift with availability — group by `schedule.date` downstream to reconstruct the calendar

  **Filter by shift name** — Only keep dinner availability:
  - Zenchef: any operation
  - IF: `{{ $json.name === "Dinner" }}`

  **AI agent tool** — This node is marked as **usable as a tool** with a rich LLM-optimized description, so an n8n AI agent can call it to answer questions like "Is restaurant X available next Saturday?". To use it:
  1. Open the **AI Agent** node and click **+ Tool**.
  2. Search for **Zenchef** in the tool picker (it appears under the AI > Tools subcategory).
  3. Configure the **Restaurant ID** — the agent will fill in dates and operations automatically based on the user's question.
  No extra prompt engineering is needed; the tool description tells the LLM about every parameter, operation, and output field.

  ## Publishing

  This package is published to npm with [provenance statements](https://docs.npmjs.com/generating-provenance-statements), which lets you verify that a published version was built from this repository's source code using GitHub Actions — not from a developer's local machine.

  Provenance is generated automatically by the `publish.yml` workflow. To publish a new version:

  1. Run locally `npm run release`, this will use `release-it` to update the version, generate the changelog and push a tag. Pushing a tag triggers a Github Actions workflow.
  2. The GitHub Actions workflow will lint, build, and publish the package to npm with a signed provenance attestation.

  ### Prerequisites

  - An npm **granular access token** with publish permissions, stored as a repository secret named `NPM_TOKEN` in your GitHub repo settings.
  - The publish workflow requires `id-token: write` permission (already configured) so GitHub can mint the OIDC token used by [Sigstore](https://www.sigstore.dev/) to sign the provenance statement.

  Once published, the provenance badge will appear on the package's [npm page](https://www.npmjs.com/package/n8n-nodes-zenchef), allowing anyone to trace the published artifact back to the exact source commit and workflow run that produced it.

  ## Resources

  - [n8n community nodes documentation](https://docs.n8n.io/integrations/#community-nodes)
  - [Zenchef website](https://www.zenchef.com)

  ## Error management

  The Zenchef API does not return errors in a consistent format. The same logical error can surface as a `400` plain-text response or a `200` with a JSON `"error"` key. The node's `postReceive` error handler (`handle-errors.ts`) detects each shape and throws a `NodeApiError` with a clear, actionable message so the n8n user immediately understands what went wrong.

  Note: if the API returns data but every day is closed or every shift lacks availability, the node throws a "No availability data returned" error rather than returning an empty result silently.

  The full catalogue of error shapes — along with the test suite used to discover them, the decision tree, and the translation table — is documented in [`ERROR.md`](ERROR.md).

ai_documentation_summary:
  {"purpose":"Query restaurant availability data from Zenchef's public booking widget API for use in n8n workflows. It returns available shifts by day for a specified restaurant and date range without requiring private API access.","capabilities":["Check availability for a single day","Check availability for a date range (up to about 30 days)","Check availability for a full month","Check availability for upcoming N days","Filter results by exact number of guests","Return one item per available shift per day with schedule, guest capacity, and booking window details"],"authentication":"None required; uses Zenchef's public unauthenticated widget API","commonUseCases":["Display or process restaurant availability in an automation","Check open reservation slots before sending booking-related notifications","Populate workflows with daily, monthly, or upcoming availability data for one or more restaurants"],"limitations":["Only accesses the public widget API, not Zenchef's private/authenticated API","No authentication, rate-limiting contract, or SLA is provided","Not intended for aggressive polling, scraping, or high-frequency automated use","Date range searches are limited to about 30 days","Returns only available shifts; closed days and unavailable shifts are excluded"],"relatedNodes":[]}


node_type: n8n-nodes-zadarma-app.zadarma
package_name: n8n-nodes-zadarma-app
display_name: Zadarma
description: Zadarma official n8n integration node
category: Community
development_style: declarative
version: 1
credentials_required: []
outputs:
  [
  "main"
  ]

updated_at: 2026-07-14 14:40:34
author_name: zadarma
author_github_url: https://github.com/zadarma/n8n-nodes-zadarma.git
npm_package_name: n8n-nodes-zadarma-app
npm_version: 0.1.6
community_fetched_at: 2026-07-14T14:40:34.488Z
ai_summary_generated_at: 2026-06-26 10:29:17
properties_schema:
  [
    {
      "name": "resource",
      "type": "options",
      "default": "zadarmaIntegration",
      "options": [
        {
          "name": "Zadarma Integration",
          "value": "zadarmaIntegration"
        }
      ],
      "displayName": "Resource",
      "noDataExpression": true
    },
    {
      "name": "operation",
      "type": "options",
      "default": "auth",
      "options": [
        {
          "name": "Create Callback",
          "value": "create_callback",
          "action": "Create callback",
          "description": "Create callback request"
        },
        {
          "name": "Create Customer",
          "value": "create_customer",
          "action": "Create customer",
          "description": "Create Teamsale customer"
        },
        {
          "name": "Create Event",
          "value": "create_event",
          "action": "Create event",
          "description": "Create Teamsale event"
        },
        {
          "name": "Create Feed",
          "value": "create_customer_feed",
          "action": "Create feed",
          "description": "Create a customer's feed"
        },
        {
          "name": "Create Lead",
          "value": "create_lead",
          "action": "Create lead",
          "description": "Create Teamsale lead"
        },
        {
          "name": "Create SMS",
          "value": "create_sms",
          "action": "Create SMS",
          "description": "Create SMS request"
        },
        {
          "name": "Get Account Info",
          "value": "get_account_info",
          "action": "Get account info",
          "description": "Get account info request"
        },
        {
          "name": "Get Customer By Phone Number",
          "value": "get_customer_id_by_phone",
          "action": "Get customer by phone number",
          "description": "Get Teamsale customer ID by phone number"
        },
        {
          "name": "Get Lead By Phone Number",
          "value": "get_lead_id_by_phone",
          "action": "Get lead by phone number",
          "description": "Get Teamsale lead ID by phone number"
        },
        {
          "name": "Get List Of Customers By Phone Number",
          "value": "get_customer_id_list_by_phone",
          "action": "Get list of customers by phone number",
          "description": "Get list of customers by phone number request"
        },
        {
          "name": "Get SMS Senders List",
          "value": "get_sms_senders_list",
          "action": "Get SMS senders list",
          "description": "Get SMS senders list request"
        },
        {
          "name": "List Customers By Phone Number",
          "value": "get_lead_id_list_by_phone",
          "action": "List customers by phone number",
          "description": "Get list of Teamsale leads by phone number"
        },
        {
          "name": "Receive FB Message",
          "value": "receive_facebook_message",
          "action": "Receive FB message",
          "description": "Get Facebook message request"
        },
        {
          "name": "Update Customer",
          "value": "update_customer",
          "action": "Update customer",
          "description": "Update Teamsale customer"
        },
        {
          "name": "Update Event",
          "value": "update_event",
          "action": "Update event",
          "description": "Update Teamsale event"
        },
        {
          "name": "Update Lead",
          "value": "update_lead",
          "action": "Update lead",
          "description": "Update Teamsale lead"
        },
        {
          "name": "Verify Authentication",
          "value": "auth",
          "action": "Verify authentication",
          "description": "Verify authentication action request"
        }
      ],
      "displayName": "Operation",
      "displayOptions": {
        "show": {
          "resource": [
            "zadarmaIntegration"
          ]
        }
      },
      "noDataExpression": true
    }
  ]

operations:
  [
    {
      "name": "Create Callback",
      "value": "create_callback",
      "action": "Create callback",
      "description": "Create callback request",
      "resource": "zadarmaIntegration"
    },
    {
      "name": "Create Customer",
      "value": "create_customer",
      "action": "Create customer",
      "description": "Create Teamsale customer",
      "resource": "zadarmaIntegration"
    },
    {
      "name": "Create Event",
      "value": "create_event",
      "action": "Create event",
      "description": "Create Teamsale event",
      "resource": "zadarmaIntegration"
    },
    {
      "name": "Create Feed",
      "value": "create_customer_feed",
      "action": "Create feed",
      "description": "Create a customer's feed",
      "resource": "zadarmaIntegration"
    },
    {
      "name": "Create Lead",
      "value": "create_lead",
      "action": "Create lead",
      "description": "Create Teamsale lead",
      "resource": "zadarmaIntegration"
    },
    {
      "name": "Create SMS",
      "value": "create_sms",
      "action": "Create SMS",
      "description": "Create SMS request",
      "resource": "zadarmaIntegration"
    },
    {
      "name": "Get Account Info",
      "value": "get_account_info",
      "action": "Get account info",
      "description": "Get account info request",
      "resource": "zadarmaIntegration"
    },
    {
      "name": "Get Customer By Phone Number",
      "value": "get_customer_id_by_phone",
      "action": "Get customer by phone number",
      "description": "Get Teamsale customer ID by phone number",
      "resource": "zadarmaIntegration"
    },
    {
      "name": "Get Lead By Phone Number",
      "value": "get_lead_id_by_phone",
      "action": "Get lead by phone number",
      "description": "Get Teamsale lead ID by phone number",
      "resource": "zadarmaIntegration"
    },
    {
      "name": "Get List Of Customers By Phone Number",
      "value": "get_customer_id_list_by_phone",
      "action": "Get list of customers by phone number",
      "description": "Get list of customers by phone number request",
      "resource": "zadarmaIntegration"
    },
    {
      "name": "Get SMS Senders List",
      "value": "get_sms_senders_list",
      "action": "Get SMS senders list",
      "description": "Get SMS senders list request",
      "resource": "zadarmaIntegration"
    },
    {
      "name": "List Customers By Phone Number",
      "value": "get_lead_id_list_by_phone",
      "action": "List customers by phone number",
      "description": "Get list of Teamsale leads by phone number",
      "resource": "zadarmaIntegration"
    },
    {
      "name": "Receive FB Message",
      "value": "receive_facebook_message",
      "action": "Receive FB message",
      "description": "Get Facebook message request",
      "resource": "zadarmaIntegration"
    },
    {
      "name": "Update Customer",
      "value": "update_customer",
      "action": "Update customer",
      "description": "Update Teamsale customer",
      "resource": "zadarmaIntegration"
    },
    {
      "name": "Update Event",
      "value": "update_event",
      "action": "Update event",
      "description": "Update Teamsale event",
      "resource": "zadarmaIntegration"
    },
    {
      "name": "Update Lead",
      "value": "update_lead",
      "action": "Update lead",
      "description": "Update Teamsale lead",
      "resource": "zadarmaIntegration"
    },
    {
      "name": "Verify Authentication",
      "value": "auth",
      "action": "Verify authentication",
      "description": "Verify authentication action request",
      "resource": "zadarmaIntegration"
    }
  ]

npm_readme:
  # n8n-nodes-zadarma-app

  n8n node for integrating **Zadarma** with n8n workflows.

  This node allows you to connect n8n with Zadarma API to automate lead management, callbacks, and other CRM-related operations.

  ## Features

  - Create and update entities in Teamsale CRM
  - Trigger workflows based on Zadarma events (callbacks, leads, etc.)
  - Supports error handling and `continueOnFail`

  ## Installation

  ### Community nodes (recommended)

  In n8n:

  1. Go to Settings -> Community nodes -> Install.
  2. Find the app by npm Package Name "n8n-nodes-zadarma-app"

  After install:

  1. Credentials → Create New → Zadarma
  2. Enter API Key + Secret from https://my.zadarma.com/marketplace/
  3. Add Zadarma node to workflow


  Restart n8n if required.

  ### Manual installation

  ```bash
  npm install n8n-nodes-zadarma-app
  ```

  ---

  Or for local development (restart n8n after setting the variable):

  ```bash
  export N8N_CUSTOM_EXTENSIONS=/path/to/custom-nodes
  ```

  ## Usage example

  You can find more examples in our instruction page https://zadarma.com/en/support/instructions/n8n/

  ### Sending SMS from n8n

  Trigger - receiving a third-party Webhook, action - sending an SMS.
  In the **Workflows** section, click the **Create workflow** button then **Add first step** find and select the Webhook node.

  #### Trigger - Webhook

  Select the type of **Webhook URL**: Test URL or Production URL. In the **HTTP Method** field, choose the POST request type.

  #### Webhook settings

  Click **Listen for event** and copy the URL to which the Webhooks will be sent. After that, you need to receive a test Webhook so that the trigger can obtain a list of parameters for further use. For testing, we can send a POST request to our Webhook, for example using a bash script:

  ```bash
  curl -X POST https://n8n.yourdomain.com/webhook-test/a5bbc64f-2714-446a-bfff-01b0fedbxab0 \
  -H "Content-Type: application/json" \
  -d '{"text": "Wake up, Neo...", "phone": "+44201234567"}'
  ```

  - https://n8n.yourdomain.com/webhook-test/a5bbc64f-2714-446a-bfff-01b0fedbxab0 - The URL of your webhook in n8n.
  Next, add a second step to your Workflow. 
  In the search, find Zadarma and select the **Create SMS** action.

  #### Zadarma Create SMS

  On the left side of the window, the structure of the test Webhook notification received in the previous step will be displayed. Drag the required parameters into the corresponding fields for sending the SMS. In our example, two parameters were received, **Text** and **Phone**, which will be used as the SMS text and the recipient’s phone number respectively. You may have any other parameters.

  #### SMS Parameters

  Close the window. The setup is complete. Your Workflow is ready to run and publish. Now, when a Webhook is received at your URL, an SMS message will be sent.


  ## Credentials

  This node requires Zadarma API credentials.

  Create new credentials in n8n:

  - API Token (required) from https://my.zadarma.com/marketplace/

  The credentials are securely stored by n8n and used for all requests to the Zadarma API.

  ## Supported Resources & Operations

  | Resource | Operations          |
  |----------|---------------------|
  | Lead     | Get, Create, Update |
  | Callback | Create              |
  | Customer | Get, Create, Update |
  | Event    | Create, Update      |
  | SMS      | Create              |

  ## License

  [MIT](LICENSE.md)

  ## Changelog

  See [CHANGELOG.md](CHANGELOG.md) for release history.

ai_documentation_summary:
  {"purpose":"Integrates Zadarma with n8n workflows to automate CRM, lead management, callbacks, SMS, and event-driven processes. It connects to the Zadarma API for creating and updating entities and reacting to Zadarma-related events.","capabilities":["Lead resource: get, create, and update leads","Callback resource: create callbacks","Customer resource: get, create, and update customers","Event resource: create and update events","SMS resource: create/send SMS messages","Trigger workflows based on Zadarma events such as callbacks and leads","Supports error handling and continueOnFail"],"authentication":"API Key + Secret (Zadarma API credentials from my.zadarma.com/marketplace)","commonUseCases":["Automatically create or update CRM records in Teamsale CRM","Send SMS notifications from workflow data","Trigger automations when Zadarma callbacks or leads are received"],"limitations":[],"relatedNodes":["Webhook"]}


