This is the full developer documentation for YepCode # Overview > Explore the documentation site for YepCode, the all-in-one platform that seamlessly connects your services and APIs with agility. Welcome to YepCode, the integration and automation tool designed for developers who love working with source code. While no-code tools have their merits, YepCode offers a compelling alternative for developers who prefer writing code over dealing with extensive drag-and-drop interfaces and complex execution graphs. It caters to those requiring advanced features like streaming information, reusable program logic, and transactional support. This documentation platform is a work in progress, and we value your feedback as we continue to improve. ## How does it work? [Section titled “How does it work?”](#how-does-it-work) YepCode allows you to create processes by implementing logic through [source code](/docs/processes), supporting two programming languages: * JavaScript * Python The platform provides a plethora of components and features to efficiently solve **real problems**. With both an IDE and an execution environment, YepCode enables automation of any software task and integration allowing to use any NPM or PyPI package. Once your YepCode process is implemented, you can [run it](/docs/executions) manually, configure [scheduled executions](/docs/executions/scheduled) (cron jobs), trigger it using [*Webhooks*](/docs/executions/webhooks), or even [embed the form](/docs/forms) on any external webpage. ## How do I get started? [Section titled “How do I get started?”](#how-do-i-get-started) Simply [create an account](https://cloud.yepcode.io) and follow the [onboarding tour](https://www.youtube.com/watch?v=yPlvTOP_l3U) integrated into the platform. ## What are the costs? [Section titled “What are the costs?”](#what-are-the-costs) Our [pricing model](https://yepcode.io/pricing) is based on a virtual coin called **Yep**. The *free plan* allows you to start using the tool with a limited amount of Yeps and some feature restrictions. # Let's do the Hello World > Learn the basics of YepCode by implementing a Hello World sample. In the world of programming tools, a **Hello World** sample is often the key to resolving initial doubts. Watch this brief video during our onboarding tour to get an overview… …but the best option is to create your account and implement it yourself! To get started, log in to your account at (if you don’t have an account yet, you can create one in seconds!). Navigate to your processes list page, which might be initially empty, but here you could see any previously created processes. Click on the `New` button and provide a name and description for this new process. For this sample, we’ll use JavaScript as the language: ![Screenshot](/docs/img/screenshots/create-new-process.png) Now you can input your source code into our editor. For this sample, you can use the following snippet: * JavaScript ```js const { context: { parameters }, } = yepcode; const message = `Hello ${parameters.name}`; console.log(message); return { theMessage: message, }; ``` * Python ```py parameters = yepcode.context.parameters message = f"Hello ${parameters['name']}." print(message) return { "theMessage": message, } ``` You should see something like this: ![Screenshot](/docs/img/screenshots/hello-world-source-code.png) As you might guess, YepCode supports input parameters. To configure them, go to the *parameters* tab and add this JSON code in the input parameters editor: ```json { "description": "The hello world input parameters", "type": "object", "title": "Hello world input parameters", "properties": { "name": { "type": "string", "description": "Type your name to receive a greeting" } }, "required": ["name"] } ``` It should look like this: ![Screenshot](/docs/img/screenshots/hello-world-input-params.png) Press the `Save` button and you’re done with your process, let’s run it! 🚀 There are multiple ways to run the process, but in this case, we’ll go with the simplest one. Just press the run button and provide the input parameters: ![Screenshot](/docs/img/screenshots/hello-world-run-params.png) After that, you’ll be redirected to the new execution page, where you can check how the execution is going and review the process output (in real-time if the process is still active): ![Screenshot](/docs/img/screenshots/hello-world-execution.png) Congratulations! Your first YepCode process is up and running. Now let’s move on to more complex tasks! # YepCode Processes > Explore the concept of YepCode processes and learn how to create a new one. In YepCode, a process is the core component responsible for implementing business logic. ![Screenshot](/docs/img/screenshots/processes-list.png) You can have as many processes as needed to address various programming challenges. In the following sections, we’ll guide you through the process creation, detailing the available configurations, and showcasing the tool modules you can leverage. # Understanding Source Code in Processes > Learn how to write business logic using the YepCode editor. In the YepCode editor, users can craft the code to implement their processes. Depending on the language selected, the script is executed in a specific engine: * We use the [NodeJS ](https://nodejs.org/)**v22** engine. This allows you to utilize nearly all functions supported by NodeJS. The code is wrapped in an `async` function, enabling the use of `await` throughout the function. * We use the [Python ](https://www.python.org/)**v3.13** engine. This supports the use of almost all functions provided by Python. ![Screenshot](/docs/img/screenshots/processes-source-code.png) For those who prefer not to reinvent the wheel, explore the [team dependencies](/docs/dependencies) to take advantage of any NPM or PyPI package. To combat the challenge of [spaghetti code](https://en.wikipedia.org/wiki/Spaghetti_code), we’ve included a module to create and use your own [Modules](/docs/processes/modules). The source code editor supports **key shortcuts**, **code formatting**, and **autocomplete features**. If you start typing `YepCode...`, you’ll see some useful snippets. ![Screenshot](/docs/img/screenshots/processes-source-code-suggestion.png) The process source code is executed sequentially. Tip In JavaScript versions, each process execution will wait while any active promise is still running. As with any other script, you can define functions and structure your code with good practices. Please follow the principles of [clean code](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882). ## Internal Helpers [Section titled “Internal Helpers”](#internal-helpers) YepCode allows you to use information from the current execution in your process. ### Access to Execution and Process Info [Section titled “Access to Execution and Process Info”](#access-to-execution-and-process-info) The basic information available for all executions includes the `id` of the current execution, the comment (if you wrote one), and the `id` and `name` of the process being executed. The code to obtain them would be: * JavaScript ```js const { id, comment } = yepcode.execution; const { id: processId, name: processName } = yepcode.execution.process; ``` * Python ```py id, comment = yepcode.execution.id, yepcode.execution.comment processId, processName = yepcode.execution.process.id, yepcode.execution.process.name ``` ### Access to Scheduled Process Info [Section titled “Access to Scheduled Process Info”](#access-to-scheduled-process-info) When you schedule a process, you also have access to the `id` of the schedule and its `comment` (if it exists). The code to obtain them would be: * JavaScript ```js const { id: scheduleId, comment: scheduleComment } = yepcode.execution.schedule; ``` * Python ```py scheduleId, scheduleComment = yepcode.execution.schedule.id, yepcode.execution.schedule.comment ``` ### Build Execution Link [Section titled “Build Execution Link”](#build-execution-link) An interestion use case for this information is to build the exact execution link to send it by email: * JavaScript ```js const executionLink = `${yepcode.team.baseUrl}/${yepcode.team.slug}/executions/${yepcode.execution.id}`; ``` * Python ```py executionLink = f"{yepcode.team.baseUrl}/{yepcode.team.slug}/executions/{yepcode.execution.id}" ``` ### Access to Team Info [Section titled “Access to Team Info”](#access-to-team-info) You can access information about your team through the `yepcode.team` object, which exposes the following properties: * `timezone`: The timezone set in your team. * `slug`: The unique identifier of your team. * `baseUrl`: The base URL of your YepCode instance. ```json { "timezone": "Europe/Madrid", "slug": "mmuino", "baseUrl": "https://cloud.yepcode.io" } ``` Note The team timezone will also be the timezone used for any date manipulation in the execution. * JavaScript ```js const { timezone, slug, baseUrl } = yepcode.team; ``` * Python ```py timezone, slug, baseUrl = yepcode.team.timezone, yepcode.team.slug, yepcode.team.baseUrl ``` ### Run another process asynchronously [Section titled “Run another process asynchronously”](#run-another-process-asynchronously) Execute a process asynchronously within the same execution. ```plaintext yepcode.processes.run(process-identifier [, options]); ``` * `process-identifier`: The process uuid or slug to run. * `options`: * `parameters`: An object containing the parameters to pass to the process. *(optional)* * `tag`: Specify a [process version](/docs/processes/process-versioning) tag to run a concrete version of your process. *(optional)* * `comment`: A comment for the new execution. *(optional)* * `settings`: An object containing the settings to pass to the process. *(optional)* - JavaScript ```js yepcode.processes.run("hello-world", { parameters: { name: "Jane Doe", }, tag: "latest", comment: "Running hello-world from execution", settings: { agentPoolSlug: "eu-west-1", }, }); ``` - Python ```py yepcode.processes.run("hello-world", { "parameters": { "name": "Jane Doe", }, "tag": "latest", "comment": "Running hello-world from execution", "settings": { "agentPoolSlug": "eu-west-1", }, }) ``` ## Return Value [Section titled “Return Value”](#return-value) YepCode allows your processes to return a value. This is very insteresting, especially when starting executions using webhooks or forms. You could manage this result value in your client. The syntax to return one object would be: * JavaScript ```js return { message: "Hello from YepCode!" }; ``` * Python ```py return { "message": "Hello from YepCode!" }; ``` You can view it on the [execution detail](/docs/executions#execution-detail) page and also utilize it with the [sync webhooks](/docs/executions/webhooks) feature. ### Return Custom Status Codes [Section titled “Return Custom Status Codes”](#return-custom-status-codes) Custom status code and a custom message are also supported. This is useful in many cases, but the most common one is probably error handling. For example, if you want to return a 404 error, but don’t want the execution to end in an error status. To do that, you just need to return an object with the following structure: * JavaScript ```js try { // simulate an error throw new Error("Oops! Something went wrong."); } catch (e) { return { status: 418, body: { error: { message: e.message, stack: e.stack, }, }, headers: { "X-Custom-Header": "I am a custom header", }, }; } ``` * Python ```py import traceback try: # simulate an error raise Exception("Oops! Something went wrong."); except Exception as e: return { "status": 418, "body": { "error": { "message": e, "stack": traceback.format_exc(), }, }, "headers": { "X-Custom-Header": "I am a custom header", }, }; ``` The magic lies in `status`, `body` and `headers` properties. Tip You can return a JSON or plain string as body. The `Content-Type` header will be set automatically. ### Transient Return Values [Section titled “Transient Return Values”](#transient-return-values) In some cases, you may want to not store the return value of your process, for example, when sensitive data is returned. For this cases, YepCode allows you to set a result as [transient](https://en.wikipedia.org/wiki/Transient_\(computer_programming\)), so this result is not stored in the database. For these cases, the stored result will be the `[transient]` replacement. Tip If you call your process by a webhook in sync mode, you will be able to get the result in that call. To make a result transient, just follow this structure: * JavaScript ```js return { isTransient: true, body: { foo: "bar" }, }; ``` Of course, you can combine this with previously shown properties. For example: ```js return { isTransient: true, status: 201, body: { foo: "bar" }, headers: { "X-Custom-Header": "I am a custom header", }, }; ``` * Python ```py return { "isTransient": True, "body": { "foo": "bar" }, }; ``` Of course, you can combine this with previously shown properties. For example: ```py return { "isTransient": True, "status": 201, "body": { "foo": "bar" }, "headers": { "X-Custom-Header": "I am a custom header", }, }; ``` ## Logging [Section titled “Logging”](#logging) YepCode allows to generate log entries that can be seen then in [execution detail](/docs/executions#execution-detail) view. * JavaScript In JavaScript you may use the `console` logger methods: ```js console.log(`This is an INFO message`); console.debug(`This is a DEBUG message`); console.info(`This is an INFO message`); console.warn(`This is a WARNING message`); console.error(`This is an ERROR message`); ``` * Python In Python the log level is set to WARNING, but YepCode exposes a `logger` object that has DEBUG level, so you may use it. The `print` method also generates a INFO log message: ```py print("This is an INFO message"); logger.debug("This is a DEBUG message"); logger.info("This is an INFO message"); logger.warn("This is a WARNING message"); logger.error("This is an ERROR message"); ``` This is how you’ll see the logs in the execution detail: ![Screenshot](/docs/img/screenshots/log-output.png) # Process Input Parameters > Learn how to configure process input parameters to gather information from users. When working with YepCode processes, you can configure input parameters to gather information from users before starting an [on-demand](/docs/executions/on-demand) or [scheduled](/docs/executions/scheduled) (cron job) execution. Input parameters also play a role in defining [webhook](/docs/executions/webhooks) bodies. The process edition includes a JSON editor which is used to define the process input parameter form. In your process source code, you can access the provided input parameters using the following helper: * JavaScript ```js const { context: { parameters }, } = yepcode; ``` * Python ```py parameters = yepcode.context.parameters ``` With parameters defined, you can request any information needed to run your process. Forms can range from simple: ![Screenshot](/docs/img/screenshots/processes-input-params-sample.png) …to more complex configurations: ![Screenshot](/docs/img/screenshots/processes-input-params-preview.png) ## File Inputs and YepCode Storage [Section titled “File Inputs and YepCode Storage”](#file-inputs-and-yepcode-storage) When a form field is configured as a file input, submitted files are automatically uploaded to [YepCode Storage](/docs/storage) before your process starts. That means your process receives a storage reference for each uploaded file, so you can directly download or process files with `yepcode.storage` helpers. Here is a basic file input example: ```json { "title": "Upload Form", "type": "object", "properties": { "inputFile": { "title": "Upload a file", "type": "string", "ui": { "ui:widget": "file" } } }, "required": ["inputFile"] } ``` Tip Uploaded files are stored in your team’s storage space and count toward your [storage limits](/docs/plans-and-limits#storage). If files are only needed temporarily, you can remove them at the end of your process. After the file is uploaded, the execution input parameters will contain the storage path of the uploaded file, and you can access it using the `yepcode.storage.download()` helper. See the [YepCode Storage](/docs/storage) documentation for more details. ## Form Builder [Section titled “Form Builder”](#form-builder) YepCode provides a JSON Form Builder that allows you to manage input parameters without any coding. ![Screenshot](/docs/img/screenshots/form-builder.png) You can create new input parameters, modify existing ones, or delete unnecessary ones. ![Screenshot](/docs/img/screenshots/form-builder-modify.png) ## Parameters Definition [Section titled “Parameters Definition”](#parameters-definition) We use the JSON Schema form specification, and the library we use to render the form is [react-jsonschema-form](https://rjsf-team.github.io/react-jsonschema-form/docs/). This allows you to use advanced configurations, such as [dependencies](https://rjsf-team.github.io/react-jsonschema-form/docs/usage/dependencies), which enable you to change fields based on entered data. Additionally, YepCode offers extra attributes to enhance your experience: ### Sensitive Properties [Section titled “Sensitive Properties”](#sensitive-properties) Properties marked as sensitive are treated as passwords. They are stored encrypted in the database and won’t be shown in the UI. Here you have an example of a simple form with a sensitive property: ```json { "title": "Input parameters", "type": "object", "properties": { "apiKey": { "title": "The API Key", "type": "string", "isSensitive": true } }, "required": ["apiKey"] } ``` ### Transient properties [Section titled “Transient properties”](#transient-properties) [Transient](https://en.wikipedia.org/wiki/Transient_\(computer_programming\)) properties are only available for the execution and won’t be stored in the database. An execution which receives transient parameters cannot be rerun, as these type of parameters won’t be available. They are shown with `[transient]` in the UI. Here you have an example of a simple form with a transient property: ```json { "title": "Input parameters", "type": "object", "properties": { "fileContent": { "title": "The content of the file", "type": "string", "isTransient": true } }, "required": ["fileContent"] } ``` ### Validation [Section titled “Validation”](#validation) Validation is supported by this form specification and is checked upon form submission. ![Screenshot](/docs/img/screenshots/processes-input-params-validation.png) Tip By default, validation won’t be enforced if the execution starts using non-submit form methods (e.g., [webhooks](/docs/executions/webhooks) or [API](https://cloud.yepcode.io/api/rest/public/swagger-ui/index.html)). If you want to enable this validation for all start methods, just activate the `Validate parameters schema` in the [settings](/docs/settings) page. If you want to enforce validation, but for some process you want to allow additional properties, there is [a flag for this behaviour](https://json-schema.org/understanding-json-schema/reference/object#additionalproperties). ### Content Customization [Section titled “Content Customization”](#content-customization) To provide greater flexibility to the forms and the content they display (titles, descriptions, help messages), we have improved and extended the schema to support markdown rendering using [markdown](https://www.markdownguide.org/basic-syntax/). With this functionality, you can format text in a simple and easy way to make it more readable. Here you have one sample: JSON Schema attribute using Markdown ```json "oneStringField": { "title": "![alt text](https://yepcode.io/logo.svg) *[yepcode](https://yepcode.io)* form title", "description": "[yepcode](https://yepcode.io) form description", "type": "string" }, ``` ## Full sample [Section titled “Full sample”](#full-sample) Here’s a complete example of a Form and its schema: ```json { "title": "Full [yepcode forms](https://yepcode.io) form sample", "description": "This is a sample form specification showing all available attribute types for [yepcode forms](https://yepcode.io)", "type": "object", "properties": { "oneStringField": { "title": "![alt text](https://yepcode.io/logo.svg) *[yepcode](https://yepcode.io)* form title", "description": "Visit [yepcode](https://yepcode.io) form description", "type": "string" }, "onePasswordField": { "title": "One password field", "type": "string", "description": "Password shoul be: \n 1. At least 12 characters long \n 2. Include a combination of uppercase and lowercase letters \n 3. At least one special character such as @, #, $, %", "isSensitive": true, "ui": { "ui:placeholder": "Use a secure password" } }, "oneHiddenField": { "title": "One hidden field", "type": "string", "ui": { "ui:widget": "hidden" } }, "oneIntegerField": { "title": "One integer field with range", "description": "Values must be between 0 and 500", "type": "integer", "minimum": 0, "maximum": 500 }, "oneBooleanField": { "title": "One boolean field with [link](https://yepcode.io)", "type": "boolean" }, "oneEmailField": { "title": "One email field", "type": "string", "format": "email" }, "oneTextAreaField": { "title": "One textarea field", "type": "string", "description": "> Block quote description", "ui": { "ui:widget": "textarea" } }, "oneColorField": { "title": "One color field", "type": "string", "ui": { "ui:widget": "color" } }, "oneFileField": { "title": "One file field", "type": "string", "ui": { "ui:widget": "file" } }, "oneObjectField": { "title": "One object field", "description": "This sample has two nested fields.", "required": [ "anotherString", "anotherInteger" ], "type": "object", "properties": { "anotherString": { "type": "string" }, "anotherInteger": { "type": "number", "minimum": -180, "maximum": 180 } } }, "oneStringArrayField": { "title": "One string array field", "type": "array", "items": { "type": "string" } }, "oneObjectsArrayField": { "title": "One object array field", "type": "array", "items": { "type": "object", "properties": { "oneProperty": { "description": "One property", "type": "string" }, "anotherProperty": { "description": "Another property", "type": "string" } } } }, "oneRadioField": { "title": "One string radio field", "type": "string", "ui": { "ui:widget": "radio" }, "oneOf": [ { "const": "option-1", "title": "Option 1 Label" }, { "const": "option-2", "title": "Option 2 Label" }, { "const": "option-3", "title": "Option 3 Label" } ] }, "oneCheckboxField": { "title": "One string checkboxes field", "type": "array", "ui": { "ui:widget": "checkboxes" }, "items": { "type": "string", "enum": [ "option 1", "option 2", "option 3" ] }, "uniqueItems": true }, "oneSelectField": { "title": "One string select field", "type": "string", "ui": { "ui:placeholder": "Pick one option" }, "enum": [ "option 1", "option 2", "option 3" ] }, "oneJsonParameter": { "title": "A JSON field", "description": "Block quote description", "type": "object", "ui": { "ui:field": "json" } }, "anotherBooleanField": { "title": "A input that shows other inputs", "type": "boolean" } }, "dependencies": { "anotherBooleanField": { "oneOf": [ { "properties": { "anotherBooleanField": { "enum": [ true ] }, "aDependencyValueProperty": { "title": "This is shown when anotherBooleanField is true", "type": "string" } } }, { "properties": { "anotherBooleanField": { "enum": [ false ] }, "aDependencyValueProperty": { "title": "This is shown when anotherBooleanField is false", "type": "string" } } } ] } }, "required": [ "oneStringField" ], "ui": { "ui:submitButtonOptions": { "submitText": "Click me!" } }, "withBranding": true, "embedFormOptions": { "loadingOverlayContent": "Creating new user...", "withBranding": true, "theme": "dark", "themeStylesheet": "", "loadingOverlayDisabled": false, "locale": "es" } } ``` # The process README > Learn how to document YepCode processes using a Markdown file. In YepCode processes, documentation is key. We’ve made it easy for you by providing a dedicated `README` tab in the process editor. This tab allows you to add essential information that introduces and explains the purpose of your source code. ![Screenshot](/docs/img/screenshots/processes-readme.png) Similar to input parameters, you can preview the rendered README with its [Markdown syntax](https://en.wikipedia.org/wiki/Markdown). ![Screenshot](/docs/img/screenshots/processes-readme-preview.png) # Dashboard > Explore and configure details of a YepCode process through the Dashboard page. The Dashboard page provides a comprehensive view of details and settings for a YepCode process. To access it, navigate to the process page and click on the gear icon at the top right of the screen: ![Screenshot](/docs/img/screenshots/dashboard-icon.png) ## Details [Section titled “Details”](#details) The initial page presents all available process configurations: ![Screenshot](/docs/img/screenshots/dashboard-details.png) * **General**: * **Name**: process name (must be unique across all processes). * **Slug**: friendly process identifier (must be unique across all processes). You can use it in [Webhooks](/docs/executions/webhooks) and [Forms](/docs/forms) instead of the process ID. * **Description**: process description. * **Forms**: Enable or disable forms integration for this process. This feature allows you to embed process input parameter forms in any webpage. Refer to the full [form documentation](/docs/forms) for more details. * **Visibility**: Toggle between [public](/docs/processes/shared) and private. When your process is public, you can edit the process URL token (must be unique across all processes). ## Versions [Section titled “Versions”](#versions) Explore detailed information about all your [process versions](/docs/processes/process-versioning) in the Versions tab. If your process has no versions, this tab will not be visible. ![Screenshot](/docs/img/screenshots/versions-details.png) ## Schedules [Section titled “Schedules”](#schedules) View every [scheduled configuration](/docs/executions/scheduled) (cron jobs and one-time schedules) for the process in the Schedules tab. ![Screenshot](/docs/img/screenshots/dashboard-scheduled.png) ## Executions [Section titled “Executions”](#executions) Track all process [executions](/docs/executions) in the Executions tab. ![Screenshot](/docs/img/screenshots/dashboard-executions.png) # Using User Modules > Learn how YepCode supports the use of user libraries to be used in processes. YepCode Modules allow you to define an isolated set of JavaScript or Python functions for reuse in any of your processes. These modules are designed to help share functions across processes, solve business logic problems, encapsulate access to services, and more. ![Screenshot](/docs/img/screenshots/modules-list.png) Modules function slightly differently in JavaScript and Python. Here’s a guide for both: * JavaScript To use a module, use the custom import syntax in the process (or other module) where you want to utilize it. ```js const { myFunc } = yepcode.import("your-module"); ``` Tip Modules also support [versioning](/docs/processes/process-versioning) and aliases, and if you want to import one specific module version or alias, just add a second parameter to the import sentence: ```js const { myFunc } = yepcode.import("your-module", "v1.0"); ``` You can have as many modules as needed, and they work like any CommonJS module, exporting the functions you want to use from process source code. For example, a JavaScript module exporting a function to say hello: ```js module.exports = () => console.log("Hello world!"); ``` To use this library from a YepCode process named *say\_hello*, the code would be: ```js const sayHello = yepcode.import("say_hello"); sayHello(); ``` A module can also export several functions: ```js const sayHelloToMike = () => console.log("Hello Mike!"); const sayHelloToDavid = () => console.log("Hello David!"); module.exports = { sayHelloToMike, sayHelloToDavid }; ``` To use these functions, read them from the returned object: ```js const sayHelloModule = yepcode.import("say_hello"); sayHelloModule.sayHelloToMike(); sayHelloModule.sayHelloToDavid(); ``` Caution When you import a module, you can’t use variables as module names. They must be plain strings: ```js const moduleName = "my-module"; const { myFunc } = yepcode.import(moduleName); // ❌ This won't work ``` * Python To use a module, use the custom import syntax in the process (or other module) where you want to use it. ```py my_func = yepcode.import_module("your-module"); ``` Tip Modules also support [versioning](/docs/processes/process-versioning) and aliases, and if you want to import one specific module version or alias, just add a second parameter to the import sentence: ```py my_func = yepcode.import_module("your-module", "v1.0") ``` You can have as many modules as needed, and they work like any Python module. For example, a Python module exporting several functions: ```py def say_hello_to_mike(): print("Hello Mike!") def say_hello_to_david(): print("Hello David!") ``` To use these functions, read them from the returned object: ```py say_hello_module = yepcode.import_module("say_hello"); say_hello_module.say_hello_to_mike() say_hello_module.say_hello_to_david() ``` Caution When you import a module, you can’t use variables as module names. They must be plain strings: ```py module_name = "my-module" my_func = yepcode.import_module(module_name) # ❌ This won't work ``` Note Modules referenced in any process cannot be **renamed** or **deleted**. This prevents breaking active [schedules](/docs/executions/scheduled) (cron jobs), [webhooks](/docs/executions/webhooks), or [forms](/docs/forms) that trigger the process execution. ## Writing Modules from Process Edition Screen [Section titled “Writing Modules from Process Edition Screen”](#writing-modules-from-process-edition-screen) You can easily view and change modules from the process edition page by opening a component with this shortcut: ![Screenshot](/docs/img/screenshots/modules-source-code-bottom-bar.png) A modal window then shows you the defined modules, making it easy to modify or consult them. ![Screenshot](/docs/img/screenshots/modules-from-editor.png) # Using Team Variables > Explore how YepCode supports the use of variables that may contain sensitive information. YepCode team variables allow you to define key-value pairs for use in process source code. These variables are versatile, serving purposes such as storing configuration parameters used across various processes or safeguarding sensitive information like passwords or API keys (using the secured flag). ![Screenshot](/docs/img/screenshots/team-variables-list.png) When you click on the `New` icon, you can specify the variable name and value, and check whether it is secured. ![Screenshot](/docs/img/screenshots/team-variables-new.png) To use these team variables in process source code, you may use just plain JavaScript or Python env vars syntax (or use the `yepcode.env` approach): * JavaScript ```js const apiKey = process.env.KRAKEN_API_KEY; // or const apiKey = yepcode.env.KRAKEN_API_KEY; ``` * Python ```py api_key = os.getenv("KRAKEN_API_KEY") # or api_key = yepcode.env.KRAKEN_API_KEY ``` Subsequently, `apiKey` will contain the value defined in the team variable regardless of whether it was marked as secured or not. Exercise caution to avoid logging or transmitting it from the code. # Using Local Disk > Learn how to use the local disk to store temporal files in your processes. YepCode provides a temporary directory for storing files during process execution. This directory is accessible through the `TMP_DATA_DIR` environment variable and is perfect for storing temporary files, processing data, or creating intermediate files that need to be accessed during your process execution. Note **File Size Limits**: Be mindful of file sizes when writing to the temporary directory, as there may be storage limits depending on your YepCode plan. See our [plans and limits](/docs/plans-and-limits#file-system-limits) page for more information. * JavaScript In JavaScript, you can access the temporary directory using `process.env.TMP_DATA_DIR`. Here’s how to use it: ```js const fs = require('fs'); const path = require('path'); // Get the temporary directory path const tmpDir = process.env.TMP_DATA_DIR; // Create a file in the temporary directory const filePath = path.join(tmpDir, 'my-temp-file.txt'); fs.writeFileSync(filePath, 'Hello from YepCode!'); // Read the file back const content = fs.readFileSync(filePath, 'utf8'); console.log('File content:', content); // List files in the temporary directory const files = fs.readdirSync(tmpDir); console.log('Files in temp directory:', files); ``` ### Example: Using Streams for Large Files [Section titled “Example: Using Streams for Large Files”](#example-using-streams-for-large-files) ```js const fs = require('fs'); const path = require('path'); const tmpDir = process.env.TMP_DATA_DIR; // Write a large file using streams const filePath = path.join(tmpDir, 'large-file.txt'); const writeStream = fs.createWriteStream(filePath); // Write data in chunks for (let i = 0; i < 100; i++) { writeStream.write(`Data line ${i}\n`); } writeStream.end(); console.log('Large file created successfully'); // Read the file using streams const readStream = fs.createReadStream(filePath, { encoding: 'utf8' }); let lineCount = 0; readStream.on('data', (chunk) => { const lines = chunk.split('\n'); lineCount += lines.length - 1; }); readStream.on('end', () => { console.log(`File contains ${lineCount} lines`); }); ``` * Python In Python, you can access the temporary directory using `os.environ.get('TMP_DATA_DIR')`. Here’s how to use it: ```py import os # Get the temporary directory path tmp_dir = os.environ.get('TMP_DATA_DIR') # Create a file in the temporary directory file_path = os.path.join(tmp_dir, 'my-temp-file.txt') with open(file_path, 'w') as f: f.write('Hello from YepCode!') # Read the file back with open(file_path, 'r') as f: content = f.read() print('File content:', content) # List files in the temporary directory files = os.listdir(tmp_dir) print('Files in temp directory:', files) ``` ### Example: Processing CSV Data [Section titled “Example: Processing CSV Data”](#example-processing-csv-data) ```py import os import csv # Write CSV data to temporary file csv_data = ( "name,age,city\n" "John,30,New York\n" "Jane,25,Los Angeles\n" "Bob,35,Chicago\n" ) csv_path = os.path.join(os.environ.get('TMP_DATA_DIR'), 'users.csv') with open(csv_path, 'w') as f: f.write(csv_data) # Process the CSV file data = [] with open(csv_path, 'r') as f: reader = csv.DictReader(f) for row in reader: data.append(row) print('Processed data:', data) ``` Caution **Temporary Nature**: Files stored in `TMP_DATA_DIR` are automatically cleaned up after process execution. Do not rely on these files persisting between executions. ## Use Cases [Section titled “Use Cases”](#use-cases) * **Data Processing**: Store intermediate files during data transformation workflows * **File Format Conversion**: Create temporary files for format conversion operations * **Logging**: Write detailed logs that can be processed or uploaded elsewhere * **Caching**: Store temporary cache files for repeated operations within the same execution * **File Upload Processing**: Store uploaded files temporarily before processing or forwarding ## Working with YepCode Storage [Section titled “Working with YepCode Storage”](#working-with-yepcode-storage) Local disk and [YepCode Storage](/docs/storage) work excellently together for comprehensive file handling workflows. Here are common patterns: ### Uploading Local Files to Storage [Section titled “Uploading Local Files to Storage”](#uploading-local-files-to-storage) After creating files in the temporary directory, you can upload them to persistent storage: * JavaScript ```js const fs = require('fs'); const path = require('path'); // Create a file in local disk const tmpDir = process.env.TMP_DATA_DIR; const localFilePath = path.join(tmpDir, 'processed-data.csv'); // Generate some data and write to local file const csvData = 'name,age,city\nJohn,30,New York\nJane,25,Los Angeles'; fs.writeFileSync(localFilePath, csvData); // Upload to YepCode Storage for persistence await yepcode.storage.upload('exports/processed-data.csv', fs.createReadStream(localFilePath)); console.log('File uploaded to storage successfully'); ``` * Python ```py import os # Create a file in local disk tmp_dir = os.environ.get('TMP_DATA_DIR') local_file_path = os.path.join(tmp_dir, 'processed-data.csv') # Generate some data and write to local file csv_data = 'name,age,city\nJohn,30,New York\nJane,25,Los Angeles' with open(local_file_path, 'w') as f: f.write(csv_data) # Upload to YepCode Storage for persistence with open(local_file_path, 'rb') as f: obj = yepcode.storage.upload('exports/processed-data.csv', f) print(f'File uploaded to storage: {obj.name}') ``` ### Downloading from Storage for Local Processing [Section titled “Downloading from Storage for Local Processing”](#downloading-from-storage-for-local-processing) When you need to process files that don’t work well with streams, download them to local disk: * JavaScript ```js const fs = require('fs'); const path = require('path'); // Download file from storage to local disk const tmpDir = process.env.TMP_DATA_DIR; const localFilePath = path.join(tmpDir, 'downloaded-file.json'); const stream = await yepcode.storage.download('data/input-file.json'); stream.pipe(fs.createWriteStream(localFilePath)); // Now process the file locally (e.g., with libraries that need file paths) const content = fs.readFileSync(localFilePath, 'utf8'); const data = JSON.parse(content); // Process the data... const processedData = data.map(item => ({ ...item, processed: true })); // Save processed result back to local disk const outputPath = path.join(tmpDir, 'processed-output.json'); fs.writeFileSync(outputPath, JSON.stringify(processedData, null, 2)); // Upload processed result back to storage await yepcode.storage.upload('results/processed-output.json', fs.createReadStream(outputPath)); ``` * Python ```py import os import json # Download file from storage to local disk tmp_dir = os.environ.get('TMP_DATA_DIR') local_file_path = os.path.join(tmp_dir, 'downloaded-file.json') content = yepcode.storage.download('data/input-file.json') with open(local_file_path, 'wb') as f: f.write(content) # Now process the file locally (e.g., with libraries that need file paths) with open(local_file_path, 'r') as f: data = json.load(f) # Process the data... processed_data = [{**item, 'processed': True} for item in data] # Save processed result back to local disk output_path = os.path.join(tmp_dir, 'processed-output.json') with open(output_path, 'w') as f: json.dump(processed_data, f, indent=2) # Upload processed result back to storage with open(output_path, 'rb') as f: obj = yepcode.storage.upload('results/processed-output.json', f) print(f'Processed file uploaded: {obj.name}') ``` ### Best Practices for Local Disk + Storage Workflows [Section titled “Best Practices for Local Disk + Storage Workflows”](#best-practices-for-local-disk--storage-workflows) 1. **Use Local Disk for Processing**: When you need to work with files that require specific file paths or libraries that don’t support streams 2. **Use Storage for Persistence**: Upload important results to storage for long-term access and sharing 3. **Clean Up**: Remember that local disk files are automatically cleaned up, but storage files persist until manually deleted 4. **Error Handling**: Always handle potential failures in both local disk operations and storage uploads/downloads For more information about YepCode Storage capabilities, see the [Storage documentation](/docs/storage). # Duplicate a Process > Learn how to duplicate a YepCode process for efficient reuse of logic or structure. In many instances, when creating a new process, you might want to leverage the logic or structure of another process that closely aligns with your requirements. The duplicate option in YepCode comes in handy, accelerating your development speed. ![Screenshot](/docs/img/screenshots/processes-duplication-preview.png) A new process is created with a name that combines the original process name and the current timestamp. ![Screenshot](/docs/img/screenshots/processes-duplication-result.png) # Import and Export processes > Learn how to import/export YepCode processes using JSON format. YepCode enables you to effortlessly import and export processes using the JSON format. This feature is highly advantageous, allowing you to quickly share processes and create local backups. Caution This code example uses deprecated credentials: ```js const spacexClient = yepcode.integration.graphql('spacex-api') ``` Follow this [guide](/docs/credentials-migration-guide) to migrate your credentials. \[Sample] Find SpaceX launches.json ```json { "id": "0f32e404-d02a-4db7-83a1-603a1900622f", "name": "[Sample] Find SpaceX launches", "description": "This process retrieves SpaceX launches information and displays it in a textual format.", "readme": null, "script": { "sourceCode": "const { context: { parameters } } = yepcode\nconst { DateTime } = require(\"luxon\");\n\nconst spacexClient = yepcode.integration.graphql('spacex-api')\n\nspacexClient.request(\n `\n query launchesPast($limit: Int) {\n launchesPast(limit: $limit) {\n mission_name\n launch_date_utc\n launch_site {\n site_name_long\n }\n links {\n video_link\n wikipedia\n }\n rocket {\n rocket_name\n rocket_type\n }\n launch_year\n launch_success\n }\n }\n `,\n { limit: parameters.limit }\n )\n .then((data) => {\n data.launchesPast.forEach((launch => {\n console.log(\"Mission \" + launch.mission_name + \" used a \" + launch.rocket.rocket_name + \" rocket, and took place on \" + DateTime.fromISO(launch.launch_date_utc).toRFC2822() + \", being the rocket launched from \" + launch.launch_site.site_name_long + \". \" + (launch.links.video_link ? \"You can see a video on \" + launch.links.video_link + \". \": \"\") + (launch.links.wikipedia ? \"Wikipedia page is available at \" + launch.links.wikipedia + \".\" : \"\"));\n }))\n })\n .catch((error) => {\n console.error(JSON.stringify(error, undefined, 2));\n throw error;\n });\n", "parametersSchema": "{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"type\":\"object\",\"title\":\"SpaceX launches process\",\"required\":[\"limit\"],\"properties\":{\"limit\":{\"type\":\"number\",\"description\":\"How many launches do you want to retrieve?\"}}}" } } ``` *** You can import from processes page by clicking on the cloud upload icon. ![Screenshot](/docs/img/screenshots/processes-import.png) *** You can export from the process or processes pages by clicking `Export as file` in the three dots menu. ![Screenshot](/docs/img/screenshots/processes-export-one.png) ![Screenshot](/docs/img/screenshots/processes-export-two.png) # Process Versioning > Learn how to use process versions and alias in YepCode. YepCode allows you to manage different versions of your processes and modules, so then you may start executions using an specific version source code. ## Manage versions [Section titled “Manage versions”](#manage-versions) You can publish a version from the process pages by clicking `Publish version` in the three dots menu. ![Screenshot](/docs/img/screenshots/publish-version.png) This action will display a form where you should write a tag for the new process version and a comment for the version if desired. ![Screenshot](/docs/img/screenshots/publish-version-form.png) Once you create the version, you can view its code by changing to it in the version selector. It’s important to note that you cannot edit the code of a published version. To continue editing your process, simply return to the current version using the selector and continue coding! ![Screenshot](/docs/img/screenshots/process-version-change.png) Having a version published, you can select that version source code to be used when you start any process execution. ## Run now with version [Section titled “Run now with version”](#run-now-with-version) During one [on-demand execution](/docs/executions/on-demand), you can select the version source code be used: ![Screenshot](/docs/img/screenshots/process-version-run-now.png) ## Scheduled execution with version [Section titled “Scheduled execution with version”](#scheduled-execution-with-version) For [scheduled executions](/docs/executions/scheduled) (cron jobs), you can also select the version source code be used: ![Screenshot](/docs/img/screenshots/process-version-scheduler.png) ## Webhook execution with version [Section titled “Webhook execution with version”](#webhook-execution-with-version) For [webhook executions](/docs/executions/webhooks), you should pass the `Yep-Version-Tag` HTTP Header to use one version source code: ![Screenshot](/docs/img/screenshots/process-version-webhook.png) ## Version aliases [Section titled “Version aliases”](#version-aliases) To maximize the utility of versions, we introduce version aliases—pointers to a process or module version that you can update with ease. ![Screenshot](/docs/img/screenshots/process-version-alias-create.png) This feature addresses the need to change the version used by an external service without deploying changes to that service. Consider a scenario where an external service calls YepCode via a webhook, specifying a process version (e.g., `v1.0`) in the invocation header. When you release a new process version (e.g., `v2.0`) and want to switch to it, updating the external service can be cumbersome. Instead, by using an alias in the webhook invocation (e.g., `stable`), initially linked to version `v1.0`, you can seamlessly transition to version `v2.0` by simply updating the alias in the YepCode UI. This approach eliminates the need to modify the external service, making version management more efficient. ![Screenshot](/docs/img/screenshots/process-version-alias-list.png) Version aliases can be used exactly in the same scenarios where process versions are available: run now, webhooks or scheduled configurations (cron jobs). ## Modules versioning and aliases [Section titled “Modules versioning and aliases”](#modules-versioning-and-aliases) YepCode Modules also support versions and aliases. See [modules docs page](/docs/processes/modules) to see how one version or alias can be selected during module import. ![Screenshot](/docs/img/screenshots/process-version-module.png) # Share a process > An explanation about how to share and view public processes YepCode allows you to share your processes. To do this, you have to set the process visibility as public in the [dashboard](/docs/processes/dashboard). When your process is public, you can copy the link from the [dashboard](/docs/processes/dashboard) or access it from the sidebar. ![Screenshot](/docs/img/screenshots/share-process-btn.png) This button will display a modal where you can copy the public process link. ![Screenshot](/docs/img/screenshots/share-process-modal.png) Anyone who accesses the link can view your public process. ![Screenshot](/docs/img/screenshots/public-process.png) Tip Visit [this link](https://cloud.yepcode.io/public/sandbox/processes/sample-dollar-cost-averaging-on-crypto-exchange) to see a public process in our sandbox team. # Process Tags > Learn how to use YepCode process tags to organize and filter your processes. Tags are labels that help you organize related processes into logical groups. By tagging your processes, you can easily filter and find them later. ## Adding Tags to a Process [Section titled “Adding Tags to a Process”](#adding-tags-to-a-process) You can add tags to any process through the editor’s right sidebar, where all current tags for that process are displayed. ![Screenshot](/docs/img/screenshots/process-tags.png) To add a tag: 1. Click in the tag input field. 2. Either: * Type a new tag name to create a fresh tag and hit **Enter** to add it. * Select an existing tag from the dropdown that appears. ![Screenshot](/docs/img/screenshots/process-add-existing-tag.png) Tip Using existing tags helps maintain consistency. Tags are shared across all processes. ## Filtering Processes by Tags [Section titled “Filtering Processes by Tags”](#filtering-processes-by-tags) Once you’ve tagged your processes, you can filter them: 1. Navigate to your processes list 2. Use the tag filter input to select one or more tags 3. Click **Search** to apply the filter ![Screenshot](/docs/img/screenshots/processes-filter-by-tags.png) This is especially useful as your collection of processes grows. ## Using tags for MCP toolsets [Section titled “Using tags for MCP toolsets”](#using-tags-for-mcp-toolsets) When using the [YepCode MCP Server](/docs/mcp-server): * **`mcp-tool`** (default): Tag a process with `mcp-tool` and it is automatically exposed as an MCP tool — no configuration needed * **Custom tags** (e.g. `core`, `automation`): Add those tags to `YEPCODE_MCP_TOOLS` so the MCP server discovers them Each tagged process becomes a callable tool; the tool name is the process slug. See [Configuration](/docs/mcp-server/configuration#processes-as-tools) for details. # YepCode Executions > Discover how to manage YepCode process executions. As you may have guessed, the purpose of every process is to be executed. Every started execution will be listed in the executions page, informing about its execution status, the start and execution times. ![Screenshot](/docs/img/screenshots/executions-list.png) ## Execution detail [Section titled “Execution detail”](#execution-detail) Every execution has its execution details page, showing all the related information, every output logs and its return value. ![Screenshot](/docs/img/screenshots/executions-detail.png) When an execution of a process ends, you may want to run it again. You can do it through the rerun button. This will run the process with the same parameters as the previous run. ![Screenshot](/docs/img/screenshots/executions-detail-rerun.png) In the following sections, we’ll show the approaches that can be used to start one process executions. # On Demand Executions > Discover how to run a process on demand. The simplest execution type is the on demand, where the user starts the execution manually. You only have to press the `Run` button from the process page ![Screenshot](/docs/img/screenshots/executions-run-now-icon.png) and the input params form will be shown (if configured). If you want, you can also add a comment about the execution. ![Screenshot](/docs/img/screenshots/executions-run-now.png) After providing the required information, the execution will start, showing the execution details page. Note If your process has no versions, the version selector won’t appear. # Scheduled Executions > Set up cron jobs and scheduled runs for your YepCode processes. Use fixed dates or cron expressions. A manual execution may not be the best if you are trying to automate tasks. A much more interesting execution approach is the scheduled one—ideal for **cron jobs** and recurring automations. YepCode supports two scheduled configurations, fixed date and cron expression, and both of them are configured from the process page using the calendar icon: ![Screenshot](/docs/img/screenshots/executions-schedule-icon.png) ## Fixed Date Execution [Section titled “Fixed Date Execution”](#fixed-date-execution) A process can be configured to be executed on a certain date and time. With this configuration, the process will be executed when that moment is reached. In this sample, we are scheduling a process execution for `27/11/2021 at 10 am`: ![Screenshot](/docs/img/screenshots/executions-schedule-fixed.png) ## Periodic Executions (cron jobs) [Section titled “Periodic Executions (cron jobs)”](#periodic-executions-cron-jobs) If you need to run **cron jobs** or start an execution with a periodic configuration, you can use the integrated form that allows you to build the periodicity, or if you prefer, we also accept a [cron expression](https://en.wikipedia.org/wiki/Cron). ![Screenshot](/docs/img/screenshots/executions-schedule.png) ## Pause a Periodic Execution [Section titled “Pause a Periodic Execution”](#pause-a-periodic-execution) If you need to pause a periodic execution, you can use the schedule summary to pause the execution. When you want to resume it, you will only have to activate it from the schedule summary. ![Screenshot](/docs/img/screenshots/executions-schedule-pause.png) # Webhook Executions > Discover how to configure and start a YepCode process using webhooks. [Webhooks](https://en.wikipedia.org/wiki/Webhook) are endpoints that you can provide to other external ecosystems. This is very handy because it allows you to trigger process executions from external systems. ## Configuration [Section titled “Configuration”](#configuration) From the process page, you may find the *Webhook configuration* section on the right sidebar. ![Screenshot](/docs/img/screenshots/triggers-section.png) Once you press the `Add +` button, you can create a webhook passing optional authentication params. If you don’t provide a user and password, no authentication would be needed to start the process, so take care about it! ![Screenshot](/docs/img/screenshots/create-webhook.png) After creating the webhook, you can see: * The generated URL link, points to the process using its [Slug](/docs/processes/dashboard#details), which you can configure. * The [cURL](https://curl.se/) command. ![Screenshot](/docs/img/screenshots/webhook-ready.png) Now in the process *Webhook configuration* section you’ll see the created webhook. From the options menu you can: * Update the previously created auth in `Edit auth` * See the URL link and [cURL](https://curl.se/) command in `Show endpoint` (also by clicking on the webhook itself). ![Screenshot](/docs/img/screenshots/webhook-options.png) Congrats! Your webhook is ready for external requests. ## Invoking Webhooks Externally [Section titled “Invoking Webhooks Externally”](#invoking-webhooks-externally) Make an HTTP `GET` or `POST` to test your configured webhook, use a tool like [Postman](https://www.postman.com/), [Insomnia](https://insomnia.rest/) or `curl` in your terminal. Payloads passed from the request body are included in [YepCode parameters](/docs/processes/input-params). For example, this implementation would perform echoes from provided parameters: * JavaScript ```js // my echo process const { context: { parameters }, } = yepcode; return parameters; ``` * Python ```py # my echo process parameters = yepcode.context.parameters return parameters; ``` Invoke it using `curl` from the terminal with some parameters: ```sh curl -X GET -H "Content-Type: application/json" \ https://cloud.yepcode.io/api/your-team/webhooks/your-process-slug?name=John%20Doe # {"name":"John Doe"} ``` The same example using `POST`, parameters in `POST` are passed as request body: ```sh curl -X POST -H "Content-Type: application/json" -d '{"name": "John Doe"}' \ https://cloud.yepcode.io/api/your-team/webhooks/your-process-slug # {"name":"John Doe"} ``` ### Request Context [Section titled “Request Context”](#request-context) When a webhook is invoked, YepCode provides access to the request context through `yepcode.context.request`. This object includes: * `headers`: The request headers. * `rawBody (Js) / raw_body (Py)`: The request raw body. * `query`: The request query parameters. * `method`: The request method. - JavaScript ```js const { context: { request: { headers, rawBody, query, method } }, } = yepcode; ``` - Python ```py request = yepcode.context.request headers = request.get("headers", {}) raw_body = request.get("raw_body", "") query = request.get("query", "") method = request.get("method", "") ``` For example, we could send a header signature to improve our process security: ```sh curl --location --request POST 'https://cloud.yepcode.io/api/your-team/webhooks/your-process-slug' \ --header 'Content-Type: application/json' \ --header 'YepCode-Signature: yp_test_y4Fb38t5RngUZiZSzFC4c4lZHFKHcC' ``` And validate that signature matches in the process: * JavaScript ```js const { context: { request }, } = yepcode; if ( request.headers["yepcode-signature"] !== "yp_test_y4Fb38t5RngUZiZSzFC4c4lZHFKHcC" ) { return { status: 400, body: { error: { message: "Invalid signature. Double check the 'YepCode-Signature' header", }, }, }; } ``` * Python ```py request = yepcode.context.request if request.get("headers", {}).get("yepcode-signature", "") != "yp_test_y4Fb38t5RngUZiZSzFC4c4lZHFKHcC": return { "status": 400, "body": { "error": { "message": "Invalid signature. Double check the 'YepCode-Signature' header", }, }, }; ``` For better security, you can verify signatures using the raw body content. This approach ensures the integrity of the entire payload by creating a hash of the request body: ```sh SECRET_KEY="your-secret-key" PAYLOAD='{"name": "John Doe", "amount": 100}' # Generate a signature with your secret key using HMAC-SHA256 SIGNATURE=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$SECRET_KEY" | sed 's/^.* //') curl --location --request POST 'https://cloud.yepcode.io/api//webhooks/' \ --header 'Content-Type: application/json' \ --header "X-Signature-SHA256: sha256=$SIGNATURE" \ --data-raw "$PAYLOAD" ``` And validate the signature in your process: * JavaScript ```js const crypto = require("crypto"); const { context: { request }, } = yepcode; const secretKey = process.env.WEBHOOK_SECRET_KEY; // Store your secret securely with YepCode team variables const receivedSignature = request.headers["x-signature-sha256"]; const expectedSignature = `sha256=${crypto .createHmac("sha256", secretKey) .update(request.rawBody) .digest("hex")}`; if (receivedSignature !== expectedSignature) { return { status: 401, body: { error: { message: "Invalid signature. Payload integrity check failed.", }, }, }; } return { status: 200, body: { message: "Signature verified successfully", }, } ``` * Python ```py import hmac import hashlib import os def main(): # Store your secret securely with YepCode team variables secret_key = os.getenv("WEBHOOK_SECRET_KEY") request = yepcode.context.request received_signature = request.get("headers", {}).get("x-signature-sha256", "") expected_signature = f"sha256={hmac.new(secret_key.encode(), request.get('raw_body', '').encode(), hashlib.sha256).hexdigest()}" if received_signature != expected_signature: return { "status": 401, "body": { "error": { "message": "Invalid signature. Payload integrity check failed.", }, }, } return { "status": 200, "body": { "message": "Signature verified successfully", }, } ``` There are also some predefined **headers** that you can use to control the execution of your process: * **Yep-Version-Tag:** Specify your [process version](/docs/processes/process-versioning) tag to run a concrete version of your process. *(optional)* * **Yep-Async:** Choose to run the webhook synchronously or asynchronously. Sync executions will wait the process to finish before returning the response, while async executions will respond instantly with 201 HTTP code and a JSON informing about execution id. *(optional)* default:**false** * **Yep-Initiated-By:** Provide an additional level of abstraction to identify who is initiating requests to the YepCode endpoints. Its value will be recorded and can be consulted in the [audit events](/docs/audit-events). This allows clients to track and review the specific initiators of API requests for auditing and compliance purposes. It is optional and can be used in addition to the standard user authentication. *(optional)* * **Yep-Agent-Pool:** If your team has configured more than one *Agent Pool* you can specify in which one the process will execute. Otherwise, the default pool will be used. *(optional)* * **Yep-Comment:** The comment for the new execution. *(optional)* Note For synchronous requests, if execution last more than 60 seconds, invokations will result in a Request Timeout (HTTP Code 408), but execution will continue in YepCode. Result body will be something like: ```json {"status":408,"message":"Timed out before execution with id 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' ended"} ``` ### Query Parameters [Section titled “Query Parameters”](#query-parameters) * **async:** Same as **Yep-Async** header. It takes precedence over the header. *(optional)* default:**false** * **async\_response:** Customize the response body for async webhook executions. When provided, this content will be returned as the response body instead of the default JSON. Set to `false` to return no body. *(optional)* #### Custom Async Response Body [Section titled “Custom Async Response Body”](#custom-async-response-body) By default, async webhook executions return a JSON response like this: ```json {"id":"cb045e6a-48e4-4bc4-a7be-a09bca0ffbe5","status":"CREATED","data":null} ``` However, you can customize this response by using the `async_response` query parameter. This allows you to provide a custom message or content that will be returned as the response body instead of the default JSON. **Examples:** ```sh # Custom response message curl -X POST "https://cloud.yepcode.io/api/your-team/webhooks/your-process-slug?async=true&async_response=Working%20on%20it" # Response: Working on it # No response body curl -X POST "https://cloud.yepcode.io/api/your-team/webhooks/your-process-slug?async=true&async_response=false" # Response: (empty body) # Default behavior (no async_response parameter) curl -X POST "https://cloud.yepcode.io/api/your-team/webhooks/your-process-slug?async=true" # Response: {"id":"cb045e6a-48e4-4bc4-a7be-a09bca0ffbe5","status":"CREATED","data":null} ``` Note The HTTP status codes remain unchanged when using the `async_response` parameter. Only the response body content is customized. ### Response Headers [Section titled “Response Headers”](#response-headers) When you start executions using a webhook, you may want to set some headers in the response to the client. This can be useful to inform the client about the execution status, or to provide a link to the execution details. This can be done by setting the response headers in the process code: * JavaScript ```js return { status: 201, // The HTTP status code to return to the client headers: { your-custom-header: "the-header-value" // The header to return to the client }, body: { message: "Any other response body" // The response body to return to the client } } ``` * Python ```py return { "status": 201, # The HTTP status code to return to the client "headers": { "your-custom-header": "the-header-value" # The header to return to the client }, "body": { "message": "Any other response body" # The response body to return to the client } } ``` There are also some predefined headers that you can use to control the execution of your async process execution: * **Yep-Execution-ID:** All requests to webhooks returns this header indicating the execution id. * **[Location header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location):** Async executions return this header indicating the location of the execution. ## Tips & Examples [Section titled “Tips & Examples”](#tips--examples) Tip The response for async executions (when you set Yep-Async: true or async query param is true) will contain a [Location header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location) with the URL of the execution Here you have some sample requests with a sandbox process: Execute current version and async mode (Yep-Async header) ```sh curl --location --request POST 'https://cloud.yepcode.io/api/sandbox/webhooks/sample-process-versions' \ --header 'Yep-Async: true' ``` Execute current version and async mode ```sh curl --location --request POST 'https://cloud.yepcode.io/api/sandbox/webhooks/sample-process-versions?async=true' \ ``` Execute concrete version and sync mode ```sh curl --location --request POST 'https://cloud.yepcode.io/api/sandbox/webhooks/sample-process-versions' \ --header 'Yep-Version-Tag: v1.0.0' \ --header 'Yep-Async: false' ``` Execute current version and sync mode (Yep-Async header) ```sh curl --location --request POST 'https://cloud.yepcode.io/api/sandbox/webhooks/sample-process-versions' \ --header 'Yep-Async: false' ``` Execute current version and sync mode ```sh curl --location --request POST 'https://cloud.yepcode.io/api/sandbox/webhooks/sample-process-versions?async=false' \ ``` Execute current version and sync mode with comment (Yep-Comment header) ```sh curl --location --request POST 'https://cloud.yepcode.io/api/sandbox/webhooks/sample-process-versions' \ --header 'Yep-Comment: execution-comment' ``` # Handle execution errors > Discover how to handle the errors of your executions. An execution of a process may fail, so probably you want to be aware when this occurs. For example, you may send the error by mail or to a slack channel. YepCode allows you to configure one of your processes to handle the errors when any execution fail. You can do it in [settings](/docs/settings) page. A process which you want to configure to handle the errors of the executions has a predefined parameters schema. You can copy from here or find it parameters schema editor actions, by doing right click in the editor. Also, you can download two process samples built in JavaScript ready to be directly imported into your team: * [Error notification using SMTP](/docs/samples/error-handler-with-smtp.json) * [Error notification using Slack](/docs/samples/error-handler-with-slack.json) Error handler process parameters schema ```js { "description": "These are the input params for an execution error handler process", "title": "Execution error handler params", "type": "object", "properties": { "execution": { "title": "Execution", "required": ["id"], "type": "object", "properties": { "id": { "type": "string" }, "comment": { "type": "string" }, "params": { "type": "object", "title": "Execution input params", "ui:schema": { "ui:field": "json" } }, "schedule": { "title": "Schedule", "type": "object", "properties": { "id": { "type": "string" }, "comment": { "type": "string" } } }, "process": { "title": "Process", "type": "object", "required": ["id"], "properties": { "id": { "type": "string" }, "name": { "type": "string" } } } } }, "error": { "title": "Error", "type": "object", "required": ["message", "stacktrace"], "properties": { "message": { "type": "string" }, "stacktrace": { "type": "string" } } } } } ``` # Account Settings > Manage your team information and account settings. In the **Settings** tab, administrators can efficiently manage team information, upgrade the account’s [pricing plan](https://yepcode.io/pricing), and delete the current team. ![Screenshot](/docs/img/screenshots/settings.png) ## Manage Subscription Plan [Section titled “Manage Subscription Plan”](#manage-subscription-plan) This area allows you to view and modify your current subscription details: * Upgrade to access additional features. * See your active plan and its limits. ![Screenshot](/docs/img/screenshots/manage-subscription-plan.png) By clicking the **upgrade plan** button, any administrator can initiate an account upgrade, unlocking a more powerful version of YepCode. The yeps consumption component display the amount of Yeps consumed in the current billing period and the remaining available Yeps. ## Delete Team [Section titled “Delete Team”](#delete-team) To delete the current team, click the `Delete team` button and type the team name. This action, performed by an administrator, results in a complete data wipe. ![Screenshot](/docs/img/screenshots/team-delete.png) # Teams > Collaborate with multiple users using YepCode teams. YepCode teams facilitate collaboration among multiple users within the same company or workgroup, providing shared workspace access to all created processes. ![Screenshot](/docs/img/screenshots/team-members.png) There are two user types within a team: **administrators** and **developers**. Developers have the ability to invite other team members. # API Credentials > Learn how to manage your API credentials to integrate with YepCode services. API credentials let you securely authenticate when integrating with YepCode.\ Each API Credential you create generates: * An **OAuth 2.0 Client Credential** (**Client ID** + **Client Secret**) to call the **YepCode REST API**. * A **YepCode Run API Token** to authenticate requests to the **YepCode Run API**. * **MCP Server endpoints** (OAuth and No-OAuth) derived from the same credential. Use these values in your integrations and rotate/delete the credential if you need to revoke access. ![Screenshot](/docs/img/screenshots/api-credentials.png) ## Available Services [Section titled “Available Services”](#available-services) ### [YepCode REST API](https://cloud.yepcode.io/api/rest/public/swagger-ui/index.html) [Section titled “YepCode REST API”](#yepcode-rest-api) Uses the **Client ID** and **Client Secret** (OAuth 2.0 Client Credentials). ### [YepCode Run](https://yepcode.io/run) [Section titled “YepCode Run”](#yepcode-run) Uses the **YepCode Run API Token**. ### MCP Server [Section titled “MCP Server”](#mcp-server) Provides OAuth and No-OAuth endpoints linked to the same credential. ## Create a new API Credential [Section titled “Create a new API Credential”](#create-a-new-api-credential) Creating an API Credential automatically generates: * An **OAuth 2.0 Client Credential** (**Client ID** + **Client Secret**) for the YepCode REST API. * A **YepCode Run API Token** for authenticating against the Run API. * **MCP endpoints** (OAuth and No-OAuth) derived from those credentials. 1. Go to the **API Credentials** tab on the [Settings](/docs/settings) page. 2. Click any **New** button (both buttons trigger the same creation flow). 3. Enter a name for the credential. 4. Click **Create**. After creation, the page will display: * **Client ID** * **Client Secret** * **Run API Token** * **MCP endpoints** (OAuth and No-OAuth variants) ![Screenshot](/docs/img/screenshots/api-credentials-new.png) ## Delete API Credential [Section titled “Delete API Credential”](#delete-api-credential) 1. Go to the **API Credentials** tab on the [settings](/docs/settings) page. 2. Click on the “Delete” button. 3. Confirm the deletion. ![Screenshot](/docs/img/screenshots/api-credentials-delete.png) # Dependencies > YepCode allows to import any JavaScript or Python package to be used in your processes. Leverage existing solutions. The software development ecosystem offers a wealth of powerful libraries that can significantly enhance your development process and productivity. To incorporate these libraries into your YepCode processes, simply specify the package name and version in the dedicated editor accessible through your team settings. This streamlined approach allows you to effortlessly integrate and utilize external dependencies: Note Custom packages can be configured in any plan, but we have some [amount limits](/docs/plans-and-limits#package-dependencies). * JavaScript We allow to use any [npmjs](https://www.npmjs.com/) packages, that must be provided with the `package.json` format. ![Screenshot](/docs/img/screenshots/dependencies-javascript.png) Tip For [enterprise plans](/docs/plans-and-limits), we support the use of your own Git repositories as JavaScript dependencies using [npm Git syntax](https://docs.npmjs.com/cli/v11/using-npm/package-spec#git-urls). For example: ```json "yepcode-pkg": "git@github.com:yepcode/yepcode-pkg.git" ``` * Python We allow to use any [Pypi](https://pypi.org/) packages, that must be provided with the `requirements.txt` format. ![Screenshot](/docs/img/screenshots/dependencies-python.png) Tip For [enterprise plans](/docs/plans-and-limits), we support the use of your own Git repositories as Python dependencies using [pip Git syntax](https://pip.pypa.io/en/stable/topics/vcs-support#git). For example: ```txt yepcode-pkg @ git+ssh://git@github.com:yepcode/yepcode-pkg.git ``` When you perform a dependency change, YepCode proceeds to install them, but process executions will use the previous version until we ensure that the installation has been successfully completed. ## Dependencies scope [Section titled “Dependencies scope”](#dependencies-scope) Dependencies will be global for your team by default, but if you need to use process scoped dependencies, you may do that enabling the flag under process dependencies settings. ![Screenshot](/docs/img/screenshots/dependencies-process-scope.png) Note Dependencies created from YepCode Run SDKs will be always process scoped. ## Dependencies guessing [Section titled “Dependencies guessing”](#dependencies-guessing) YepCode tries to guess the dependencies you use in your process and modules. You’ll see an alert if we detect that you’re using a dependency that is not installed on your team: ![Screenshot](/docs/img/screenshots/dependencies-not-available-alert.png) Just clicking the alert will open the dependencies editor where you can add the missing dependencies, and if you use the ‘Add’ button, we’ll use the last available version of the dependency. Tip Dependencies guessing is specially useful when you’re using YepCode As A Service through our [Rest API](https://cloud.yepcode.io/api/rest/public/swagger-ui/index.html). Check for example the **Create process endpoint**, that allows to send the `"autoDetect": true` configuration inside the `settings` node. With that, you may create fully executable processes and all the needed dependencies will be installed automatically. ## Use @add-package comment [Section titled “Use @add-package comment”](#use-add-package-comment) Sometimes, the dependencies guessing is not enough. You can use the `@add-package` comment to manually add a dependency to your process. You can even set the version of the dependency with the syntax `@add-package =`. Some samples about how to use it: * JavaScript Configure a dependency to use the last version ```js // @add-package openai const OpenAI = require('openai'); const client = new OpenAI({ apiKey: yepcode.env.OPENAI_API_KEY, }); async function main() { const chatCompletion = await client.chat.completions.create({ messages: [{ role: 'user', content: 'Say this is a test' }], model: 'gpt-4o', }); } main(); ``` Configure a dependency to use a specific version ```js // @add-package openai=4.79.1 const OpenAI = require('openai'); ... ``` * Python Configure a dependency to use the last version ```py # @add-package openai from openai import OpenAI client = OpenAI( api_key=yepcode.env.OPENAI_API_KEY ) chat_completion = client.chat.completions.create( messages=[ { "role": "user", "content": "Say this is a test", } ], model="gpt-4o", ) ``` Configure a dependency to use a specific version ```py # @add-package openai=1.59.8 from openai import OpenAI client = OpenAI( api_key=yepcode.env.OPENAI_API_KEY ) ... ``` Note If you have any issue with dependencies installation (like for example using a private package from some private registry), please [contact us](https://yepcode.io/contact). # Audit events > This module tracks every single event generated by your team using the platform. Gain visibility into who did what, when, and where for all user activity on YepCode Platform. When you and your team mates perform actions over YepCode resources, like for example creating a new process, invoking a webhook, or updating a resource, these events are stored. Then, they can be analyzed to see the changes in your data. This feature helps with security because they provide records of all activity, including possible suspicious activity. All audit generated events are kept although the underline entity could be deleted. For example, if some developer creates one process, performs some executions, and then removes the process, both the process and executions will be removed, but related audit events will be kept, and could be quite useful for forensic tasks. The possibility to track and see audit events is allowed for some of our [paid plans](/docs/plans-and-limits#audit-events-history). For teams with one of these plans, the team admins can access the audit events page, in which they can see a table with all audit events. Each table row can also have content, depending on the type of the event that was performed. If the audit event has content, then the row will have an arrow to uncollapse the content. ![Screenshot](/docs/img/screenshots/audit-events.png) ## Audit event attributes [Section titled “Audit event attributes”](#audit-event-attributes) For each audit event, we show the following information: * **User** → The user who performed the action. For execution events, it can also appear @webhook or @scheduler, depending on how the execution was launched. * **IP** → The IP address of the user. * **ID** → The ID of the entity that was affected. * **Type** → The type of the entity that was affected. * **Event** → The event that was performed. * **Time** → The time when the event was performed. ## Audit events types [Section titled “Audit events types”](#audit-events-types) We support the following audit event types: ### PROCESS [Section titled “PROCESS”](#process) It represents any change in the process source code, input parameters, readme, or process configuration. The available events are `CREATED`, `UPDATED`, `DELETED`, and `PUBLISHED`. For source code changes, you have a diff editor to see the changes in a very easy and clear way. ![Screenshot](/docs/img/screenshots/audit-event-source-code.png) ### MODULE [Section titled “MODULE”](#module) It represents any change in the source code of each module, supporting the `CREATED`, `UPDATED`, and `DELETED` events. ### EXECUTION [Section titled “EXECUTION”](#execution) It stores information for each started execution. The user attribute will have the special value of `scheduler` for this kind of started executions. The same for `webhook`. ### VARIABLES [Section titled “VARIABLES”](#variables) It stores information for each managed team variable, supporting events of `CREATED`, `UPDATED`, and `DELETED`. ### SCHEDULE [Section titled “SCHEDULE”](#schedule) It stores information for each managed schedule configuration, supporting events of `CREATED` and `DELETED`. ### TEAM [Section titled “TEAM”](#team) Any change in the team configuration will be stored here with the `UPDATED` event. We also have the `INVITATION SENT` event to register new member invitations. ## Export audit events [Section titled “Export audit events”](#export-audit-events) You can also export the audit events to a JSON file. For this, you need to click on the export button, at the top right of the screen, and the file download will start. # On-Premise Deployments > We provide several flavors to get YepCode deployed in your system's infrastructure. Some clients may find it interesting (or even required) to deploy YepCode in their infrastructure. The YepCode architecture is described in [this blog post](/blog/an-overview-of-yepcode-technology-stack/), and as you may guess, the deployment does not just involve a monolith project. We have thought about that, and we provide two main flavors for on-premise installations: * [Full Stack On-Premise](/docs/on-premise/full-stack) * [Only Executors Layer On-Premise](/docs/on-premise/executors) # Full Stack On-Premise > We provide an on-premise flavor where all the YepCode services are deployed. In this flavor, the entire YepCode microservices and related services (database, identity provider, etc.) are deployed. All the microservices are dockerized, and we may provide a [Helm chart](https://helm.sh/docs/topics/charts/) to deploy the entire stack in a [Kubernetes](https://kubernetes.io/) cluster. This deployment option is only available on **ENTERPRISE** plans, so please [contact us](https://yepcode.io/contact/) if you are interested in this flavor. # Executors On-Premise > We provide an on-premise flavor where only the YepCode executors layer is deployed. This is a simpler approach but very suitable to meet some clients’ needs. In this case, we only deploy the executors layer, and the rest of the services are not deployed, so you’ll use the YepCode cloud ones. This allows the processes to run in your system infrastructure but without the need to deploy the whole stack. This flavor is quite interesting under various situations: * If you don’t want to [grant access](/docs/network-access) to your internal services. As the processes’ source code runs in your systems, there is no need to open network connections from the YepCode cloud. * If you need to move large amounts of information between services deployed in your system infrastructure, and you don’t want to incur in the related network traffic cost. * If you want to remotely run code in several destinations without the need to deploy any project in each one. This may be a good use case for SaaS companies that need to get information from their clients’ systems and then return the result of processing that information. This deployment option is only available on **GROWTH** or **ENTERPRISE** plans, so please [contact us](https://yepcode.io/contact/) if you are interested in this flavor. # YepCode Forms > Initiate process executions from any webpage by embedding process input parameter forms. YepCode allows you to initiate process executions from any webpage by embedding [process input parameter](/docs/processes/input-params) forms. This feature enables each form submission to start an execution with the information filled in the form. It also allows you to manage the execution result within that webpage, including support for multistep forms! ![Screenshot](/docs/img/screenshots/form-preview.png) For a comprehensive demonstration of how YepCode Forms works, watch the full demo video below: # Getting Started with YepCode Forms > Learn how to initiate process executions from any webpage by embedding process input parameter forms. ## Enable YepCode Form [Section titled “Enable YepCode Form”](#enable-yepcode-form) The first step is to create your [YepCode process](/docs/processes) and configure the [input parameters](/docs/processes/input-params) that will define form fields. Tip The input parameters configuration for the form on the [Overview](/docs/forms) page would be: ```json { "title": "Sign-Up Form", "type": "object", "properties": { "name": { "title": "Your Name", "type": "string" }, "email": { "title": "Your Email", "type": "string", "format": "email" }, "password": { "title": "Your Password", "type": "string", "isSensitive": true, "ui": { "ui:placeholder": "Use a Secure Password" } }, "yourIdDocument": { "title": "Upload Your ID Document", "type": "string", "ui": { "ui:widget": "file" } }, "plan": { "title": "Which Plan Do You Want to Use", "type": "string", "ui": { "ui:widget": "radio" }, "enum": ["FREE", "STARTER", "GROWTH"], "default": "STARTER" } }, "required": ["name", "email", "password"], "embedFormOptions": { "loadingOverlayContent": "Creating a New User..." } } ``` With these input parameters configured, it is time to enable the forms feature. Simply visit the process [Dashboard](/docs/processes/dashboard) and enable the `Forms` flag. ![Screenshot](/docs/img/screenshots/form-enabled.png) # YepCode Form Installation > Learn how to install YepCode Forms on your website. Let’s get started by embedding the simplest version of a YepCode form, and later we’ll explore the full form configuration. ## Embedding the Form [Section titled “Embedding the Form”](#embedding-the-form) There are two methods to embed a form on any external webpage: * Using our JavaScript SDK that replaces DOM elements with forms * Using the YepCodeForm [ReactJS](https://reactjs.org/) component In both cases, you’ll need two mandatory parameters: * **yepcode-team-id**: Your team ID, available on your workspace URL `https://cloud.yepcode.io/` * **yepcode-process-id**: Your process ID, available on your process URL `https://cloud.yepcode.io//processes/`. For example, `fd7f9a83-2d3d-1af8-6c3f-b9caa68531b1` ### Method 1: Embed a Form using our JavaScript SDK [Section titled “Method 1: Embed a Form using our JavaScript SDK”](#method-1-embed-a-form-using-our-javascript-sdk) The first step is to place this snippet into the `head` tag of your website. ```html ``` It can be loaded globally on your website or just on the webpages where you want to embed forms. * Init forms using data attributes By default, the SDK looks for any DOM element containing the data attributes `data-yepcode-form-team` and `data-yepcode-form-process` and replaces each element with the full form rendering. This is the simplest version of a form: ```html
``` * Init forms using YepCode.initForm function Another approach to embed a form with our SDK is by calling a function exposed by the SDK. This function receives the DOM element selector and a JSON with the configuration: ```html
``` If you prefer to provide the DOM element itself, that is also supported: ```html
``` ### Method 2: Embed a form using `YepCodeForm` ReactJS component [Section titled “Method 2: Embed a form using YepCodeForm ReactJS component”](#method-2-embed-a-form-using-yepcodeform-reactjs-component) Note It supports ReactJS versions 17 and 18 * Install as an NPM package using your favourite package manager: ```sh yarn add @yepcode/react-forms ``` or ```sh npm install --save @yepcode/react-forms ``` * Import the component and render it in your ReactJS app: ```jsx import YepCodeForm from "@yepcode/react-forms"; const MyComponent = () => { return ( "} processId={""} /> ); }; ``` Tip If you are using a Server-Side Rendering framework like [NextJS](https://nextjs.org/), use dynamic components [with no SSR](https://nextjs.org/docs/advanced-features/dynamic-import#with-no-ssr): ```jsx import dynamic from "next/dynamic"; const YepCodeForm = dynamic(() => import("@yepcode/react-forms"), { ssr: false, }); const MyComponent = () => { return ( "} processId={""} /> ); }; ``` # YepCode Forms Customization > Explore the customization options for YepCode Forms ### Default Behavior [Section titled “Default Behavior”](#default-behavior) When you set only the `team` and `processId`, YepCode Forms exhibit the following default behavior: * The form initiates the process execution. * A loading overlay is displayed during execution with the message: “Sending information…” * Upon **success**: * The response object is logged in the JavaScript console. * The form element is replaced by the message: “The form has been successfully submitted.” * Upon **error**: * The response object is logged in the JavaScript error console. * The form element is replaced by the message: “There has been an error submitting the form.” These behaviors can be extended with the following configurations: ### Add Success or Error Callback Functions [Section titled “Add Success or Error Callback Functions”](#add-success-or-error-callback-functions) You can provide functions to manage the process execution response. This is powerful, allowing actions like retrieving records from a database and showing them to the user. The syntax for setting these functions in each approach would be: * Using data attributes ```html
``` Provide a globally available JavaScript function (called with `window.${functionName}`), that receives the generated `formId`, and the JSON result of the started execution. For example: ```html ``` The same approach works for success and error callbacks. * Using JavaScript function Simplified syntax to directly provide functions: ```html
``` * Using ReactJS component Similar syntax to the JavaScript function: ```jsx import YepCodeForm from "@yepcode/react-forms"; const MyComponent = () => { return ( "} processId={""} onSuccess={(formId, processExecutionResult, formSubmittedData) => { console.log(`Form ${formId} has been successfully submitted.`); console.log(`Sent form data was:`, formSubmittedData); console.log(`Received response was:`, processExecutionResult); }} onError={console.error} /> ); }; ``` ### Default Behaviors Using Response Information [Section titled “Default Behaviors Using Response Information”](#default-behaviors-using-response-information) We have implemented several default behaviours to handle the most common use cases: #### Show a Success Message from Process Execution [Section titled “Show a Success Message from Process Execution”](#show-a-success-message-from-process-execution) If your process execution returns a JSON containing a `message` attribute (that could include HTML code), … ![Screenshot](/docs/img/screenshots/form-return-message.png) … it will be used if form submission was successfull: ![Screenshot](/docs/img/screenshots/form-show-message.png) #### Show Inline Error Messages [Section titled “Show Inline Error Messages”](#show-inline-error-messages) Include validation errors related to the global form or specific fields. These errors are attached to the default ones that our validator already includes. For example, if you have this form schema specification: ```json { "type": "object", "title": "", "properties": { "email": { "type": "string", "title": "Your email" }, "phone": { "type": "object", "title": "Your phone contact", "properties": { "countryCode": { "title": "Country code", "type": "string" }, "number": { "title": "Number", "type": "string" } } } } } ``` And in your process execution return an error response that includes a `formErrors` object: ```js return { status: 400, body: { formErrors: { fields: { email: "Some validation error in email.", phone: { countryCode: "Some validation error in country code.", }, }, global: ["One global error.", "Other global error."], }, }, }; ``` It will be shown in the form as a validation error: ![Screenshot](/docs/img/screenshots/form-show-inline-errors.png) #### Redirect to Any URL [Section titled “Redirect to Any URL”](#redirect-to-any-url) If your process execution returns a JSON containing a `redirect` object with `url` and optionally `timeout`, the user will be redirected to that page after form submission: ```js return { redirect: { url: "https://google.com", timeout: 2000, }, }; ``` #### Run any JavaScript Callback Function [Section titled “Run any JavaScript Callback Function”](#run-any-javascript-callback-function) If your process execution returns a JSON containing a `jsCallback` attribute, that code will be executed after form submission: ```js return { jsCallback: ` analytics.track("User Registered", { email: "ada@lovelace.com" plan: "STARTER" }); `, }; ``` ### Add Initial Form Values [Section titled “Add Initial Form Values”](#add-initial-form-values) Provide a JSON object that will be used to set initial values in the form. Particularlly useful for setting hidden fields values. The syntax for setting these defaults in each approach would be: * Using data attributes ```html
``` * Using JavaScript function ```html
``` * Using ReactJS component ```jsx import YepCodeForm from "@yepcode/react-forms"; const MyComponent = () => { return ( "} processId={""} defaultValues={{ company: "Trileuco Solutions", oneHiddenField: "the-value", }} /> ); }; ``` ### Configuring YepCode Sync or Async Process Execution [Section titled “Configuring YepCode Sync or Async Process Execution”](#configuring-yepcode-sync-or-async-process-execution) By default, all process executions are synchronous. However, for long-time executions, consider starting them asynchronously. YepCode will respond instantly with a 201 HTTP code and a JSON object containing the execution ID. To set these default values, use the following syntax for each approach: * Using data attributes ```html
``` * Using JavaScript function ```html
``` * Using ReactJS component ```jsx import YepCodeForm from "@yepcode/react-forms"; const MyComponent = () => { return ( "} processId={""} async={true} /> ); }; ``` ### Adding headers to form submissions [Section titled “Adding headers to form submissions”](#adding-headers-to-form-submissions) In the same way we support [headers on webhooks](/docs/executions/webhooks#request-headers), we support headers on forms, specially interesting for the initiated by header. To set these form headers, use the following syntax for each approach: * Using data attributes ```html
``` * Using JavaScript function ```html
``` * Using ReactJS component ```jsx import YepCodeForm from "@yepcode/react-forms"; const MyComponent = () => { return ( "} processId={""} headers={{"my-custom-header": "foo"}} /> ); }; ``` ### Override the API host [Section titled “Override the API host”](#override-the-api-host) By default the form embed talks to `https://cloud.yepcode.io`. You can point it at a different backend (for example, a server running [`yepcode http`](/docs/cli#run-a-local-webhook-server) when [migrating from YepCode Cloud](/docs/migrate-from-yepcode-cloud)) by setting the host URL. * Using data attributes ```html
``` * Using JavaScript function ```html
``` * Using ReactJS component ```jsx import YepCodeForm from "@yepcode/react-forms"; const MyComponent = () => { return ( "} processId={""} hostUrl={"https://your-host"} /> ); }; ``` ### Additional Options [Section titled “Additional Options”](#additional-options) YepCode Forms support additional configuration using a JSON object called `options`. This object can be configured in the embedded script or function, or in the JSON Schema specification: * Data attributes options ```html
``` * JavaScript function options ```html
``` * ReactJS component options ```jsx import YepCodeForm from "@yepcode/react-forms"; const MyComponent = () => { return ( "} processId={""} options={{ theme: "dark (default) | light", loadingOverlayDisabled: false, loadingOverlayContent: "Sending information...", }} /> ); }; ``` * JSON Schema options Consider that this configuration will impact all instances of this embedded form. If you need to override specific settings for a particular embed, utilize the following approaches, as they take precedence over the configuration received from the platform. ![Screenshot](/docs/img/screenshots/form-embed-options.png) ### Appearance Configuration [Section titled “Appearance Configuration”](#appearance-configuration) YepCode Forms support several appearance configurations to align with your site’s styles. This configuration must be provided using the [options](/docs/forms/customization#additional-options) object and allows you to change various appearance details: * Theme & styles configuration * Disable the loading overlay * Change the loading overlay text message ```json { "theme": "dark (default) | light", "loadingOverlayDisabled": false, "loadingOverlayContent": "Sending information..." } ``` #### Themes and Styles [Section titled “Themes and Styles”](#themes-and-styles) YepCode Forms include two out-of-the-box themes, each defined using a CSS variables file: * Dark theme () ![Screenshot](/docs/img/screenshots/form-dark-theme.png) * Light theme () ![Screenshot](/docs/img/screenshots/form-light-theme.png) You can create a new theme by extending any of these CSS files and setting the `embedFormOptions` configuration `themeStylesheet`, for example: ```json "embedFormOptions": { "themeStylesheet": "https://yepcode.io/sdk/styles-theme-hurt-eyes.css" }, ``` Another alternative is to provide the CSS rules directly into the `themeStylesheet` option: ```json "embedFormOptions": { "themeStylesheet": ":root {\n--ycf-accent-color: #05e20c;\n--ycf-accent-color-darker: #be0493;}" } ``` Tip If needed, there are CSS classes that wrap the form container (`.yepcode-form-container` and `.yepcode-form-wrapper`), and the form itself (`form.yepcode-form`). For adding the same form in several pages, provide a custom class name using the form options: ```json "embedFormOptions": { "className": "white-background-form" } ``` #### Using JSON Schema for Appearance Tunning [Section titled “Using JSON Schema for Appearance Tunning”](#using-json-schema-for-appearance-tunning) YepCode Forms are rendered using `react-jsonschema-form` so all the [UI schema configuration](https://rjsf-team.github.io/react-jsonschema-form/docs/api-reference/uiSchema) from this library, is available for use. To provide greater flexibility to the forms and the content they render (titles, descriptions, help messages), we have enhanced and extended them to support **markdown**. Read more about this in [YepCode parameters](/docs/processes/input-params).” For example, to change the submit button text, add this node in your parameters schema: ```json "ui": { "ui:submitButtonOptions": { "submitText": "Click me!" } } ``` ### Variables Replacement in Form Definition [Section titled “Variables Replacement in Form Definition”](#variables-replacement-in-form-definition) Another powerful kind of personalization that YepCode Forms allow is variable replacement. This allows defining variables that could differ in each form rendering. These variables are then replaced in the form definition using the [mustache](https://mustache.github.io/) syntax. Inside the [additional options](#additional-options) config, a `variables` node can be provided and would be used to replace tokens in all the definition schema, including titles, descriptions, default values, enums, etc. Note Variables will also be pushed as payload during the form submit, so you can use them in your process source code with `yepcode.context.parameters.metadata.variables` #### Example of Variables for Content Customization [Section titled “Example of Variables for Content Customization”](#example-of-variables-for-content-customization) Let’s demonstrate how it works with an example. Suppose you want to implement an upgrade process, and depending on the new plan, you want to display the benefits. Having these form schema: ```json { "title": "Upgrade to {{newPlan}} plan", "description": "{{#benefits}}* {{.}}\n{{/benefits}}", "type": "object", "properties": { "email": { "title": "Your email", "type": "string", "format": "email" } }, "required": ["email"] } ``` You could embed it with this approach and different plan configurations: * Data attributes ```html
``` * Using JavaScript function ```html
``` * Using ReactJS component ```jsx import YepCodeForm from "@yepcode/react-forms"; const MyComponent = () => { return ( "} processId={""} options={{ variables: { newPlan: "STARTER", benefits: [ "Includes 15M Yeps / month", "Max 10 concurrent executions", "Up to 10 team members" ], }, }} /> ); }; ``` You can experience diverse form renderings. Visit the [samples page](/docs/forms/samples) to see them in action. #### $ref variables replacement [Section titled “$ref variables replacement”](#ref-variables-replacement) One more feature that opens up a world of posibilities is the `$ref` variables. With these replacement you can adapt your form schema in each embed situation, with a full replacement of some node of this schema. Suppose you have an enumeration and you need to use different options in each form embed usage. That’s possible with variables: Having this form schema: ```json { "title": "Upgrade plan", "type": "object", "properties": { "newPlan": { "title": "Your new plan", "type": "string", "enum": { "$ref": "#/variables/availablePlans" } } }, "required": ["newPlan"] } ``` You could embed it with this approach and different available plan configurations: * Data attributes ```html
``` * Using JavaScript function ```html
``` * Using ReactJS component ```jsx import YepCodeForm from "@yepcode/react-forms"; const MyComponent = () => { return ( "} processId={""} options={{ variables: { availablePlans: ["STARTER", "GROWTH"], }, }} /> ); }; ``` ### Internationalization [Section titled “Internationalization”](#internationalization) YepCode Forms allow internationalization of any visible text and default error messages. The replacements follow a [mustache](https://mustache.github.io/) syntax, and you need to use a `i18nVariables` inside the [additional options](#additional-options) config, with one index for each supported locale: ```json { "title": "{{title}}", "type": "object", "properties": { "name": { "title": "{{nameLabel}}", "type": "string" }, "email": { "title": "{{emailLabel}}", "type": "string", "format": "email", "ui": { "ui:placeholder": "{{emailPlaceholder}}" } } }, "required": ["name", "email"], "embedFormOptions": { "loadingOverlayContent": "{{overlayMessage}}", "i18nVariables": { "en": { "title": "Signup form", "nameLabel": "Your name", "emailLabel": "Your email", "emailPlaceholder": "You have to use a business email", "overlayMessage": "Creating new user..." }, "es": { "title": "Formulario de registro", "nameLabel": "Tu nombre", "emailLabel": "Tu email", "emailPlaceholder": "Debes usar un email corporativo", "overlayMessage": "Creando nuevo usuario..." } } } } ``` In your form renderization, set up a `locale` param inside the options object. Note Available locales for form errors are: `en`, `ar`, `ca`, `cs`, `de`, `es`, `fi`, `fr`, `hu`, `id`, `it`, `ja`, `ko`, `nb`, `nl`, `pl`, `pt-BR`, `ru`, `sk`, `sv`, `th`, `zh`, `zh-TW` You can also use a `fallbackLocale` param to be used if any entry doesn’t exist on the selected locale or during errors renderization if the locale is not in the previous list. Locale sample configuration using data attributes: * Data attributes ```html
``` * Using JavaScript function ```html
``` * Using ReactJS component ```jsx import YepCodeForm from "@yepcode/react-forms"; const MyComponent = () => { return ( "} processId={""} options={{ locale: "gl", fallbackLocale: "es", }} /> ); }; ``` Note Configured locale will be also pushed as payload during the form submit, so you are able to use them in your process source code just with `yepcode.context.parameters.metadata.locale` So during form renderization, the i18n variables would be replaced, and you could get different forms renderizations. Visit [samples page](/docs/forms/samples) to see more forms in action. ### Customizing behaviour with functions [Section titled “Customizing behaviour with functions”](#customizing-behaviour-with-functions) One advanced personalization feature is the posibility to extend inputs using JavaScript functions. One interesting use case could allow using some dynamic behaviour when a user is filling information. For example, using a pattern and changing the provided values, or changing one attribute value depending on another attribute value. This configuration must be provided inside the `embedFormOptions` node, and there are two types of customization: #### Global onChange Handler [Section titled “Global onChange Handler”](#global-onchange-handler) Using this configuration, you may provide a JavaScript function implementation that could receive two parameters: * `formData`: current form data values * `setFormData`: function to change form data values For example, suppose you want to fill a phone country prefix depending on the country selected: ```json "embedFormOptions": { "onChange": "phonePrefixByCountryCode = {'ES': '+34', 'US': +1, 'UK': '+44'}; formData['phonePrefix'] = phonePrefixByCountryCode[formData['countryCode']]; setFormData(formData);", } ``` #### Field Transformer Function [Section titled “Field Transformer Function”](#field-transformer-function) Using this configuration, you may provide a JavaScript function implementation that receives a `value` parameter. This function should return a new value to be set to that attribute form data. Here you have a sample that would replace a provided phone number to fit with the desired format: ```json "embedFormOptions": { "fields": { "phone": { "transformFn": "if(!value) return null; return value.replace(/^\\(?(\\d{2})\\)?[ ]?(\\d{5})-?(\\d{4})$/, '($1) $2-$3');" } } } ``` ### Modal Window [Section titled “Modal Window”](#modal-window) YepCode Forms can be shown in a modal window after the user clicks on some element. To achieve this, you only need to add all the form configuration to that element, and also include the data attribute `data-yepcode-form-modal`. Here you have one example: ```html ``` # Multi-step Forms > Multi-step forms guide for YepCode If you need to gather information from users in a multi-step approach, YepCode Forms can support you. During the execution of the first process, simply return a JSON with the next step process ID: ```js return { nextProcessId: "719d7c83-...", }; ``` By doing this, after a successfull form submission, our SDK will render the form related to the received next process identifier. Tip For a multistep form, consider changing the button title to “Next”. See [how to do that](/docs/forms/customization). In the second, third,… and successive form steps, process executions will receive the previous generated data, and execution results. This allows, for example, collecting information in several steps and using all of them in the last step. The information from previous steps is published into YepCode. If you write this code in the third step: ```js const { context: { parameters }, } = yepcode; console.log(parameters); ``` You’ll see an output like this: ```json { "attribute1FromThirdStep": "your-value", "attribute2FromThirdStep": "your-value", "steps": [ { "processId": "f3997abe3-....", "data": { "attributeFromFirstStep": "your-value" }, "result": { "executionResultAttributeFirstStep": "your-value" } }, { "processId": "f39975e3-....", "data": { "attributeFromSecondStep": "your-value" }, "result": { "executionResultAttributeSecondStep": "your-value" } } ] } ``` ## Variables in Multi-step Forms [Section titled “Variables in Multi-step Forms”](#variables-in-multi-step-forms) Default values, variables, and i18n configurations set in the first form in a multi-step flow will be applied to the next steps’ forms. Another interesting feature is to return a `variables` object in one form step execution and reuse it in the following steps. This can be done by simply returning a `variables` node in process execution result: ```js return { nextProcessId: "719d7c83-...", variables: { aNewVar: "This is a new var for next form steps", }, }; ``` # YepCode Form Samples > Explore various examples of embedded YepCode forms with React component YepCodeForm. The following presents a series of examples of embedded forms using the React component YepCodeForm. ## Basic Embedded Form [Section titled “Basic Embedded Form”](#basic-embedded-form) The next example is a basic demonstration of how to render a form for executing a process. This process accepts a name as input and returns a greeting for the entered name. Check the source code in our [sandbox account](https://cloud.yepcode.io/sandbox/processes/3b4e4494-aa66-46bb-89f0-d9f78c7a39a3). ## Form using variables [Section titled “Form using variables”](#form-using-variables) Explore a form sample that renders different content using [variables](/docs/forms/customization#variables-replacement-in-form-definition). Check the source code in our [sandbox account](https://cloud.yepcode.io/sandbox/processes/a7543eea-f280-49ad-bcd8-ef6a513da44d). ### Upgrade to STARTER [Section titled “Upgrade to STARTER”](#upgrade-to-starter) ### Upgrade to GROWTH [Section titled “Upgrade to GROWTH”](#upgrade-to-growth) ## Form Using i18nVariables [Section titled “Form Using i18nVariables”](#form-using-i18nvariables) Explore a form sample that renders content in different languages using [i18nVariables](/docs/forms/customization#internationalization). Check the source code in our [sandbox account](https://cloud.yepcode.io/sandbox/processes/a7543eea-f280-49ad-bcd8-ef6a513da44d). ### English [Section titled “English”](#english) ### Spanish [Section titled “Spanish”](#spanish) ## Open Form in Modal Window [Section titled “Open Form in Modal Window”](#open-form-in-modal-window) Explore a form sample that opens in a [modal window](/docs/forms/customization#modal-window) after clicking a button. Open the form # YepCode MCP Server > Turn your YepCode processes into MCP tools. Connect Cursor, Claude Desktop, and any MCP client. The YepCode MCP Server is an [MCP (Model Context Protocol)](https://modelcontextprotocol.io/introduction) server that enables AI platforms to interact with YepCode. Run LLM-generated scripts and expose your processes as tools that AI assistants can invoke. **Dynamic MCP tools server**: * **Expose processes as tools** — Tag with `mcp-tool` (instant) or custom tags (add to `YEPCODE_MCP_TOOLS`) * **JSON Schema parameters** — Full flexibility for inputs (types, required fields, enums, defaults) * **Polyglot** — **Python** and **Node.js** in the same server ## Built-in capabilities [Section titled “Built-in capabilities”](#built-in-capabilities) | Capability | Description | | ------------------ | ------------------------------------------------------------------------ | | **run\_code** | Execute JavaScript or Python in YepCode’s secure environment | | **Process tools** | Tag with `mcp-tool` (auto-exposed) or custom tags in `YEPCODE_MCP_TOOLS` | | **Storage** | `list_files`, `upload_file`, `download_file`, `delete_file` | | **API management** | Processes, schedules, variables, storage, executions, modules | Works with [Cursor](https://cursor.sh), [Claude Desktop](https://www.anthropic.com/news/claude-desktop), and any MCP client. ## Documentation [Section titled “Documentation”](#documentation) | Page | Description | | -------------------------------------------------- | -------------------------------------------- | | [Quickstart](/docs/mcp-server/quickstart) | Hosted + self-host, auth (OAuth vs No-OAuth) | | [Configuration](/docs/mcp-server/configuration) | Processes as tools, env vars, tool selection | | [Tool reference](/docs/mcp-server/tools-reference) | run\_code, storage, API, etc. | Tip API credentials (OAuth, MCP endpoints) are in [Settings → API Credentials](/docs/settings/api-credentials). # Quickstart > Get started with hosted or self-hosted MCP. Auth (OAuth vs No-OAuth) and configuration. ## Hosted endpoint (recommended) [Section titled “Hosted endpoint (recommended)”](#hosted-endpoint-recommended) Zero setup: the endpoint is always on at `https://cloud.yepcode.io/mcp`. **Prerequisites**: YepCode account and an [API Credential](/docs/settings/api-credentials) with MCP endpoints. ### OAuth vs No-OAuth [Section titled “OAuth vs No-OAuth”](#oauth-vs-no-oauth) | Endpoint | When to use | | ------------ | ------------------------------------------------------------------------------- | | **No-OAuth** | Simplest: token in URL or headers. Best for Cursor, Claude Desktop, prototypes. | | **OAuth** | OAuth 2.0 Client Credentials. For enterprise and central credential management. | Both come from the same API Credential. Revoke the credential to invalidate both. ### Configure (No-OAuth) [Section titled “Configure (No-OAuth)”](#configure-no-oauth) **URL with token:** ```json { "mcpServers": { "yepcode-mcp-server": { "url": "https://cloud.yepcode.io/mcp/" } } } ``` **Or with headers:** ```json { "mcpServers": { "yepcode-mcp-server": { "url": "https://cloud.yepcode.io/mcp", "headers": { "Authorization": "Bearer " } } } } ``` Replace `` with the value from [Settings → API Credentials](/docs/settings/api-credentials). ### Verification [Section titled “Verification”](#verification) 1. Tools list appears in your MCP client 2. `run_code` executes (if enabled) 3. Process tools appear (tag with `mcp-tool` for instant exposure, or add custom tags to `YEPCODE_MCP_TOOLS`) *** ## Self-host (NPX or Docker) [Section titled “Self-host (NPX or Docker)”](#self-host-npx-or-docker) For air-gapped environments or full control. Open source · MIT **[yepcode/mcp-server-js](https://github.com/yepcode/mcp-server-js)** — Star the repo, run via NPX or Docker, contribute on GitHub. **Requirements**: Node.js >= 18, API token from [Settings → API Credentials](/docs/settings/api-credentials). ### NPX [Section titled “NPX”](#npx) ```json { "mcpServers": { "yepcode-mcp-server": { "command": "npx", "args": ["-y", "@yepcode/mcp-server"], "env": { "YEPCODE_API_TOKEN": "your_api_token_here" } } } } ``` ### Docker [Section titled “Docker”](#docker) ```bash docker build -t yepcode/mcp-server . ``` ```json { "mcpServers": { "yepcode-mcp-server": { "command": "docker", "args": ["run", "-i", "--rm", "-e", "YEPCODE_API_TOKEN=your_token", "yepcode/mcp-server"] } } } ``` # Configuration > Processes as tools, environment variables, tool selection, and MCP options. ## Processes as tools [Section titled “Processes as tools”](#processes-as-tools) The MCP server can expose your YepCode processes as individual MCP tools. Each process becomes a callable tool that AI assistants can invoke. ### Default tag: `mcp-tool` [Section titled “Default tag: mcp-tool”](#default-tag-mcp-tool) Tag a process with **`mcp-tool`** and it is automatically exposed as an MCP tool. No configuration needed. ### Custom tags [Section titled “Custom tags”](#custom-tags) For custom tags, add them to `YEPCODE_MCP_TOOLS` so the MCP server discovers those processes: 1. **Tag** your process (e.g. `core`, `automation`) 2. **Include** that tag in `YEPCODE_MCP_TOOLS` (see below) 3. The process appears as a tool named after its **slug** (or `yc_` if the slug is longer than 60 characters) ### Input schema and execution [Section titled “Input schema and execution”](#input-schema-and-execution) * Each process tool accepts parameters according to the process [input schema](/docs/processes/input-params) (JSON Schema). Define a proper schema for better AI behavior. * **Sync** (default): waits for completion, returns `executionId`, `logs`, `returnValue`, `error` * **Async**: pass `synchronousExecution: false` to get `executionId` immediately **Common issues**: No process tools with custom tags? Add those tags to `YEPCODE_MCP_TOOLS`. Tool not found? Ensure tag spelling matches. See [Process tags](/docs/processes/tags) for how to add and manage tags. *** ## Environment variables [Section titled “Environment variables”](#environment-variables) | Variable | Required | Description | | --------------------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | `YEPCODE_API_TOKEN` | Yes (self-host) | API token from [Settings → API Credentials](/docs/settings/api-credentials) | | `YEPCODE_MCP_TOOLS` | No | CSV: tool categories and custom process tags. Default: built-ins on; `mcp-tool` processes auto-exposed; custom tags require explicit listing | | `YEPCODE_MCP_OPTIONS` | No | CSV: `runCodeCleanup`, `skipCodingRules` | ### YEPCODE\_MCP\_TOOLS [Section titled “YEPCODE\_MCP\_TOOLS”](#yepcode_mcp_tools) * **Built-in categories**: `run_code`, `yc_api`, `yc_api_full` * **Individual tools**: e.g. `execute_process_sync`, `get_execution` * **Custom process tags**: e.g. `core`, `automation` — add tags to expose those processes (processes tagged `mcp-tool` are always exposed; see “Processes as tools” above) ### YEPCODE\_MCP\_OPTIONS [Section titled “YEPCODE\_MCP\_OPTIONS”](#yepcode_mcp_options) | Option | Default | Effect | | ----------------- | ------- | -------------------------------------------------------------------------- | | `runCodeCleanup` | on | Keeps `run_code` source for audit when enabled | | `skipCodingRules` | off | Omits coding rules from `run_code` schema (smaller defs, less AI guidance) | ### Examples [Section titled “Examples”](#examples) **YEPCODE\_MCP\_TOOLS** — enable run\_code, basic API, and processes tagged `core`: ```json "env": { "YEPCODE_API_TOKEN": "your_token", "YEPCODE_MCP_TOOLS": "run_code,yc_api,core" } ``` **YEPCODE\_MCP\_OPTIONS** — keep run\_code source for audit and skip coding rules in the tool schema: ```json "env": { "YEPCODE_API_TOKEN": "your_token", "YEPCODE_MCP_OPTIONS": "runCodeCleanup,skipCodingRules" } ``` **Both** — combine tool selection and options: ```json "env": { "YEPCODE_API_TOKEN": "your_token", "YEPCODE_MCP_TOOLS": "run_code,yc_api,core", "YEPCODE_MCP_OPTIONS": "runCodeCleanup,skipCodingRules" } ``` *** Hosted endpoint Tool selection and options can be passed via URL query params. Example: ```plaintext https://cloud.yepcode.io/mcp/?tools=run_code,yc_api,core&mcpOptions=runCodeCleanup ``` Replace `` with your API token. Check the [API Credentials](/docs/settings/api-credentials) page for the exact URL format. # Tool reference > run_code, storage, environment, process execution, and API management tools. ## run\_code [Section titled “run\_code”](#run_code) Execute JavaScript or Python in YepCode’s secure environment. Enable via `YEPCODE_MCP_TOOLS=run_code`. **Input**: `{ code: string; options?: { language?: 'javascript'|'python'; comment?: string; settings?: object } }`\ **Response**: `{ returnValue?: unknown; logs?: string[]; error?: string }` Code runs in an isolated sandbox. Subject to [plans and limits](/docs/plans-and-limits). *** ## Environment (set\_env\_var, remove\_env\_var) [Section titled “Environment (set\_env\_var, remove\_env\_var)”](#environment-set_env_var-remove_env_var) **set\_env\_var**: `{ key: string; value: string; isSensitive?: boolean }` — `isSensitive` defaults to `true` (masked in logs)\ **remove\_env\_var**: `{ key: string }` *** ## Storage (list\_files, upload\_file, download\_file, delete\_file) [Section titled “Storage (list\_files, upload\_file, download\_file, delete\_file)”](#storage-list_files-upload_file-download_file-delete_file) Uses YepCode [Storage](/docs/storage). Input/response schemas as in the README. Supports text and base64 binary. `list_files` accepts optional `prefix`. *** ## Process execution (dynamic) [Section titled “Process execution (dynamic)”](#process-execution-dynamic) Process tools: tag with `mcp-tool` (auto-exposed) or custom tags (add to `YEPCODE_MCP_TOOLS`). See [Configuration](/docs/mcp-server/configuration#processes-as-tools). **Input**: `{ parameters?: any; options?: { tag?: string; comment?: string }; synchronousExecution?: boolean }`\ **Sync response**: `{ executionId, logs, returnValue?, error? }`\ **Async response**: `{ executionId }` Define a clear [JSON Schema](/docs/processes/input-params) for process inputs so the AI can call correctly. *** ## API management (yc\_api, yc\_api\_full) [Section titled “API management (yc\_api, yc\_api\_full)”](#api-management-yc_api-yc_api_full) Enable via `YEPCODE_MCP_TOOLS=yc_api` or `yc_api_full` (adds version management). | yc\_api | yc\_api\_full adds | | ------------------------------------------------------------- | ----------------------- | | Processes, schedules, variables, storage, executions, modules | Process/module versions | Examples: `get_processes`, `execute_process_sync`, `get_execution`, etc. Full list and payloads: [REST API Reference](https://cloud.yepcode.io/api/rest/public/swagger-ui/index.html). # YepCode Landings > Manage unique landing pages for every campaign creating customizable HTML layouts with replaceable tokens. YepCode allows to manage countless variations of landing pages effortlessly. Just create customizable HTML layouts with replaceable tokens and then generate langing instances provided the needed information. For a comprehensive demonstration of how YepCode Landings works, watch the full demo video below: ## Claim Your Access [Section titled “Claim Your Access”](#claim-your-access) Access to YepCode Landings is exclusive to some of our [paid plans](/docs/plans-and-limits#yepcode-landings). If you’re interested in trying it out, simply fill this form: ## Create your first template [Section titled “Create your first template”](#create-your-first-template) Just use the `Create` button and the form to create a template will be shown: ![Screenshot](/docs/img/screenshots/landings-edit-template.png) Each template has the following information: ### Name and slug [Section titled “Name and slug”](#name-and-slug) Just some descriptive information. ### HTML Source Code [Section titled “HTML Source Code”](#html-source-code) It’s the full HTML code that will be rendered when someone visit the landing. You can include any necessary external assets such as CSS, JavaScript files, and images within your HTML code. If required, we can provide web storage space to upload your external assets. Your HTML code can utilize replaceable tokens using the [Mustache syntax](https://mustache.github.io/mustache.5.html). These tokens will be dynamically replaced with values provided during landing creation. ```html Hello, {{name}}!

Hello, {{name}}!

``` ### Properties schema. [Section titled “Properties schema.”](#properties-schema) The tokens used in your HTML code must be defined in these properties schema, that uses the JSON Schema form specification, and the library we use to render the form is [react-jsonschema-form](https://rjsf-team.github.io/react-jsonschema-form/docs/). The `slug` and `name` attributes are mandatory, and inside the `variables` node, you coud add as may attributes as you could need (in this sample we only ask for a string field for the name): ```json { "title": "Template configuration", "type": "object", "properties": { "slug": { "type": "string", "title": "URL path", "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$" }, "name": { "type": "string", "title": "Landing name" }, "variables": { "title": "Template variables", "type": "object", "properties": { "name": { "title": "Your name", "description": "This is a variable that will be replaced in the landing render", "type": "string" } }, "required": ["name"] } }, "required": ["slug", "name"] } ``` Here you have a more complex sample, including text areas and also a input type file, that will allow you to upload files when you create the landings: ```json { "title": "Template configuration", "type": "object", "properties": { "slug": { "type": "string", "title": "URL path", "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$" }, "name": { "type": "string", "title": "Landing name" }, "variables": { "title": "Template variables", "type": "object", "properties": { "title": { "title": "Page meta title", "type": "string" }, "description": { "title": "Page meta description", "type": "string" }, "heading_title": { "title": "Heading title", "type": "string" }, "heading_text": { "title": "Heading content", "type": "string", "ui": { "ui:widget": "textarea" } }, "heading_image": { "type": "string", "format": "file", "title": "Heading image", "isTransient": true } }, "required": ["title", "description", "heading_title", "heading_text"] } }, "required": ["slug", "name"] } ``` ## Create your first landing [Section titled “Create your first landing”](#create-your-first-landing) Once you’ve defined your template layout and properties, you can begin creating landings. Simply select the desired template, and the associated properties will be displayed: ![Screenshot](/docs/img/screenshots/landing-create-landing.png) The URL path will determine the availability of your landing page. By default, it will be hosted under a YepCode domain: ```text https://landings.yepcode.io/{{your-workspace-id}}/{{your-landing-url-path}}/ ``` But you can configure a `CNAME` record so that your landing page will also be accessible under your own domain. ## Do you need something more [Section titled “Do you need something more”](#do-you-need-something-more) Just [drop us a message](https://yepcode.io/contact) if you think that YepCode Landings cover your needs you but you need some kind of help. # ✨ Yep Agent > Generate real YepCode processes from prompts, safely and iteratively. Yep Agent is a coding agent built on top of YepCode that turns a prompt into **real, runnable YepCode processes** (JavaScript or Python). It works directly on your workspace codebase (processes, modules, schemas, README files), and helps you iterate until the automation is ready to run in production. ## Where to use it [Section titled “Where to use it”](#where-to-use-it) * **In YepCode Cloud**: open any process in your team and launch Yep Agent to start prompting against your workspace. * **From the public entry point**: use the AI landing at [`/ai`](/ai) (you can create an account at [`cloud.yepcode.io`](https://cloud.yepcode.io)). ## Showcase video [Section titled “Showcase video”](#showcase-video) ## What you can do with Yep Agent [Section titled “What you can do with Yep Agent”](#what-you-can-do-with-yep-agent) * **Generate a complete process**: [source code](/docs/processes/source-code) + [input parameters schema](/docs/processes/input-params) + README. * **Create reusable modules**: extract integrations (SDK clients, helpers) into [modules](/docs/processes/modules). * **Add dependencies automatically**: use any npm/PyPI packages via [dependencies](/docs/dependencies). * **Run and validate**: trigger test executions to inspect datasources, inspect logs, and then iterate. * **Configure executions on your workspace**: like [scheduled executions](/docs/executions/scheduled) (cron jobs) once the process is correct. ## How it works (high-level) [Section titled “How it works (high-level)”](#how-it-works-high-level) Yep Agent is designed to behave like a real developer working in your repo: 1. **It analyzes your workspace** (existing processes, modules, conventions). 2. **It proposes an implementation plan** and waits for confirmation before applying changes. 3. **It generates code** incrementally (often creating modules for external APIs and helpers). 4. **It validates by executing** inside YepCode, then fixes issues based on results. ![Screenshot](/docs/img/screenshots/yep-agent-implementation-plan.png) ## Security model (why credentials stay safe) [Section titled “Security model (why credentials stay safe)”](#security-model-why-credentials-stay-safe) Yep Agent runs in a secure sandbox, aligned with YepCode’s execution model. When it needs to interact with real services (databases, third-party APIs), it does so by launching executions in your YepCode team context—where your configured credentials exist—without exposing secret values to the LLM. For guidance on managing secrets/configuration in your workspace, see [Team variables](/docs/processes/team-variables). ## Recommended workflow [Section titled “Recommended workflow”](#recommended-workflow) ### 1) Start from a clear prompt [Section titled “1) Start from a clear prompt”](#1-start-from-a-clear-prompt) Aim for one automation goal, plus constraints and outputs. Example (based on the showcase): > Scan my Supabase buckets, find TXT files, convert them to audio using ElevenLabs, and store them in an `audio/` folder. Let me pick the voice/model from my ElevenLabs account, and send a Slack notification with the converted files. ### 2) Let the agent discover what it needs [Section titled “2) Let the agent discover what it needs”](#2-let-the-agent-discover-what-it-needs) If your process needs credentials (e.g. Supabase, ElevenLabs, Slack), Yep Agent will detect that and either: * use credentials you already configured in your workspace, or * ask you to create them before it can run validations. ### 3) Confirm the plan, then iterate quickly [Section titled “3) Confirm the plan, then iterate quickly”](#3-confirm-the-plan-then-iterate-quickly) After the plan is approved, the agent will typically: * generate modules for integrations (e.g. `supabase`, `elevenlabs`) * add required dependencies * build a parameters schema so you can choose options in a form (for example voice/model) * run a test execution to verify behavior end-to-end ![Screenshot](/docs/img/screenshots/yep-agent-changing-code.png) ### 4) Debug with feedback (like a teammate) [Section titled “4) Debug with feedback (like a teammate)”](#4-debug-with-feedback-like-a-teammate) When something isn’t right, tell the agent what you observed (for example: “you didn’t find files that exist in the root folder”). It will inspect the implementation, adjust assumptions (e.g., bucket root vs a subfolder), push updated code, and re-run validations. ![Screenshot](/docs/img/screenshots/yep-agent-remote-execution.png) ### 5) Ask it to operationalize [Section titled “5) Ask it to operationalize”](#5-ask-it-to-operationalize) Once correct, ask for production wiring: * **Scheduling**: “Schedule this process every Monday at 9:00 AM.” See [scheduled executions](/docs/executions/scheduled) (cron jobs). * **User-friendly inputs**: “Expose a dropdown with titles for the voices and models.” ## Tips for great results [Section titled “Tips for great results”](#tips-for-great-results) * **Be explicit about IO**: where data comes from, where it goes, and what “done” looks like. * **Name the constraints**: folders, formats, naming conventions, rate limits, timeouts. * **Request ergonomics**: ask for good parameter schemas, defaults, and helpful descriptions. * **Prefer modules for integrations**: it keeps process code small and reusable. ## Learn more (deeper technical background) [Section titled “Learn more (deeper technical background)”](#learn-more-deeper-technical-background) If you want the behind-the-scenes architecture and security design, read the build story: [“Yep Agent: The Making Of”](/blog/yep-agent-the-making-of/). # YepCode Datastore > Explore YepCode's Datastore, a simple, fast, and powerful key-value storage system. YepCode Datastore is a robust key-value storage system that is both simple and fast. It’s designed to empower your processes through accessible [source code integration](/docs/processes/source-code/). With YepCode Datastore, you can store and retrieve data within your processes and modules, facilitating information sharing across different executions. Unlock a myriad of possibilities, including: * Preserving process states between executions (e.g., maintaining the last loaded date for use in subsequent executions of an ETL process). * Efficient session management (e.g., performing a login only if your session has expired). * Maintaining a shared team global state (e.g., tracking counters, execution usage, and more). Note YepCode Datastore is only available in our [paid plans](/pricing). See our [plans and limits](/docs/plans-and-limits#datastore) page for more information. ## Usage [Section titled “Usage”](#usage) Manipulating Datastore values is accomplished through the following YepCode commands: * JavaScript Storing data ```js await yepcode.datastore.set("key", "value"); ``` Retrieving data ```js const value = await yepcode.datastore.get("key"); ``` Deleting data ```js await yepcode.datastore.del("key"); ``` Listing keys ```js // Get all keys const allKeys = await yepcode.datastore.keys(); // Get keys matching a pattern (e.g., all keys starting with "user:") const userKeys = await yepcode.datastore.keys("user-*"); ``` Caution YepCode Datastore can only store strings or numbers. If you need to store other types of data, you should convert them to strings before storing them (ie: `JSON.stringify` for objects). * Python Storing data ```py yepcode.datastore.set("key", "value") ``` Retrieving data ```py value = yepcode.datastore.get("key") ``` Deleting data ```py yepcode.datastore.delete("key") ``` Listing keys ```py # Get all keys all_keys = yepcode.datastore.keys() # Get keys matching a pattern (e.g., all keys starting with "user:") user_keys = yepcode.datastore.keys("user-*") ``` Caution YepCode Datastore can only store strings or numbers. If you need to store other types of data, you should convert them to strings before storing them (ie: `json.dumps` for objects). # YepCode Storage > Explore YepCode's Storage system, a powerful file storage solution for your processes.. YepCode Storage is a robust file storage system designed to handle file operations within your processes. It provides a simple and efficient way to store, retrieve, and manage files through accessible [source code integration](/docs/processes/source-code/). With YepCode Storage, you can perform various file operations including: * **File Upload**: Store files from your processes or external sources * **Automatic Form Uploads**: Receive files submitted from input-parameter forms directly in storage * **File Download**: Retrieve files for processing or analysis * **File Management**: List and delete your stored files * **Signed URLs**: Generate temporary download URLs for existing files ## Use Cases [Section titled “Use Cases”](#use-cases) YepCode Storage is perfect for scenarios such as: * **Document Processing**: Store uploaded documents for analysis or transformation * **Image Processing**: Handle image files for resizing, conversion or analysis * **Data Export**: Generate and store reports, CSV files or other exports * **File Sharing**: Create temporary file storage for sharing between processes * **Backup Operations**: Store important files as part of backup workflows Note Each YepCode plan has different storage limits. For information see our [plans and limits](/docs/plans-and-limits#storage) page. ## Automatic Uploads from Input Parameter Forms [Section titled “Automatic Uploads from Input Parameter Forms”](#automatic-uploads-from-input-parameter-forms) When your process uses an input parameter form with file fields (`"ui:widget": "file"`), YepCode uploads those submitted files to storage automatically before execution starts. Inside your process code, file parameters become storage references you can use with `yepcode.storage.download()` and other storage methods. For one file field, you receive one storage path. If your form allows multiple files, you will receive an array of storage paths. * JavaScript Download a file submitted through a form ```js const { context: { parameters }, } = yepcode; const uploadedPath = parameters.inputFile; // Upload path starts with "yepcode.storage://" const fileStream = await yepcode.storage.download(uploadedPath.replace("yepcode.storage://", "")); ``` * Python Download a file submitted through a form ```py uploaded_path = yepcode.context.parameters.get("inputFile") # Upload path starts with "yepcode.storage://" content = yepcode.storage.download(uploaded_path.replace("yepcode.storage://", "")) ``` Tip This behavior lets your form integrations handle large files without passing raw browser payloads through your process parameters. ## Access Methods [Section titled “Access Methods”](#access-methods) YepCode Storage can be accessed through multiple methods, making it flexible for different use cases and integration scenarios: ### 1. From Process Source Code [Section titled “1. From Process Source Code”](#1-from-process-source-code) The most direct way to use YepCode Storage is from within your process source code using the `yepcode.storage` helper: * JavaScript Uploading a file ```js const path = require("node:path"); const localPath = path.join(process.env.TMP_DATA_DIR, "myfile.txt"); await yepcode.storage.upload("path/myfile.txt", fs.createReadStream(localPath)); ``` Listing files ```js const files = await yepcode.storage.list(); console.log(files); ``` Downloading a file ```js const path = require("node:path"); const localPath = path.join(process.env.TMP_DATA_DIR, "downloaded.txt"); const stream = await yepcode.storage.download("path/myfile.txt"); stream.pipe(fs.createWriteStream(localPath)); ``` Deleting a file ```js await yepcode.storage.delete("path/myfile.txt"); ``` Creating a signed URL ```js const signed = await yepcode.storage.createSignedUrl("path/myfile.txt"); console.log(signed.url, signed.expiresAt); const signedWithCustomExpiry = await yepcode.storage.createSignedUrl("path/myfile.txt", { expiresInSeconds: 900, }); console.log(signedWithCustomExpiry.url, signedWithCustomExpiry.expiresAt); ``` * Python Uploading a file ```py import os local_path = os.path.join(os.environ.get("TMP_DATA_DIR"), "myfile.txt") with open(local_path, "rb") as f: obj = yepcode.storage.upload("path/myfile.txt", f) print("Uploaded:", obj.name, obj.size, obj.link) ``` Listing files ```py objects = yepcode.storage.list() for obj in objects: print(obj.name, obj.size, obj.link) ``` Downloading a file ```py import os local_path = os.path.join(os.environ.get("TMP_DATA_DIR"), "downloaded.txt") content = yepcode.storage.download("path/myfile.txt") with open(local_path, "wb") as f: f.write(content) ``` Deleting a file ```py yepcode.storage.delete("myfile.txt") ``` Creating a signed URL ```py signed = yepcode.storage.create_signed_url("path/myfile.txt") print(signed.url, signed.expires_at) signed_custom = yepcode.storage.create_signed_url( "path/myfile.txt", expires_in_seconds=900 ) print(signed_custom.url, signed_custom.expires_at) ``` ### 2. From External Systems via REST API [Section titled “2. From External Systems via REST API”](#2-from-external-systems-via-rest-api) YepCode Storage is also available through our [REST API](/docs/api), allowing you to upload, download, list, delete, and create signed URLs from any external system. This enables integration with third-party applications, web services, or any system that can make HTTP requests. ### 3. Using YepCode Run SDK [Section titled “3. Using YepCode Run SDK”](#3-using-yepcode-run-sdk) You can interact with YepCode Storage from external applications using our YepCode Run SDK, available for both JavaScript and Python: * JavaScript Using YepCode Run SDK for JavaScript ```js const { YepCodeStorage } = require('@yepcode/run'); const fs = require('fs'); const storage = new YepCodeStorage({ apiToken: 'your-api-token' }); // Upload a file (using Node.js stream) await storage.upload('path/myfile.txt', fs.createReadStream('./myfile.txt')); // List files const files = await storage.list(); console.log(files); // Download a file const stream = await storage.download('path/myfile.txt'); stream.pipe(fs.createWriteStream('./downloaded.txt')); // Delete a file await storage.delete('myfile.txt'); // Create a temporary signed URL (default expiration ~1 hour) const signed = await storage.createSignedUrl('path/myfile.txt'); console.log(signed.url, signed.expiresAt); // Custom expiration const signedWithCustomExpiry = await storage.createSignedUrl('path/myfile.txt', { expiresInSeconds: 900, }); console.log(signedWithCustomExpiry.url, signedWithCustomExpiry.expiresAt); ``` Install the SDK: `npm install @yepcode/run` * Python Using YepCode Run SDK for Python ```py from yepcode_run import YepCodeStorage, YepCodeApiConfig storage = YepCodeStorage( YepCodeApiConfig(api_token='your-api-token') ) # Upload a file with open('myfile.txt', 'rb') as f: obj = storage.upload('myfile.txt', f) print('Uploaded:', obj.name, obj.size, obj.link) # List all storage objects objects = storage.list() for obj in objects: print(obj.name, obj.size, obj.link) # Download a file content = storage.download('myfile.txt') with open('downloaded.txt', 'wb') as f: f.write(content) # Delete a file storage.delete('myfile.txt') # Create a temporary signed URL (default expiration ~1 hour) signed = storage.create_signed_url('path/myfile.txt') print(signed.url, signed.expires_at) # Custom expiration signed_custom = storage.create_signed_url( 'path/myfile.txt', expires_in_seconds=900 ) print(signed_custom.url, signed_custom.expires_at) ``` Install the SDK: `pip install yepcode-run` ### 4. From AI Agents via MCP Server [Section titled “4. From AI Agents via MCP Server”](#4-from-ai-agents-via-mcp-server) YepCode Storage is available as MCP (Model Context Protocol) tools in our [MCP server](https://github.com/yepcode/mcp-server-js), making it incredibly powerful when combined with AI agents. This enables AI agents to: * Handle file-based tasks end-to-end without manual intervention * Process complex data using the full power of Python/JavaScript ecosystems * Store and retrieve results securely in the cloud * Chain multiple operations across different files and datasets When combined with our `run_code` tool, AI agents can upload files, generate and execute code to process them, and store results back to YepCode Storage automatically. Tip The combination of **YepCode Storage + MCP tools + run\_code** creates a powerful environment where AI agents can handle complex file processing workflows autonomously. ## Working with Local Disk [Section titled “Working with Local Disk”](#working-with-local-disk) YepCode Storage works seamlessly with [local disk](/docs/processes/local-disk) for comprehensive file handling workflows. This combination is particularly useful when you need to: * Process files that require specific file paths or libraries that don’t support streams * Perform complex data transformations that benefit from local file access * Handle large files that need to be processed in chunks # YepCode CLI > YepCode's Command Line Interface (CLI) allows interaction with your YepCode account through a terminal. ## Introduction [Section titled “Introduction”](#introduction) A Command Line Interface (CLI) is a text-based interface that enables users to interact with a computer program. YepCode provides both a Graphic User Interface (GUI), accessible at , and a CLI for interacting with YepCode Cloud. ## YepCode CLI [Section titled “YepCode CLI”](#yepcode-cli) The YepCode Command Line Interface facilitates interaction with YepCode Cloud directly from your local workstation’s command line. It’s particularly useful if you prefer developing and testing processes’ source code locally rather than using the web IDE of YepCode Cloud. By using YepCode CLI, you can employ version control systems like `git` to manage your code and synchronize your repository with YepCode Cloud. In essence, the CLI allows you to run commands such as `clone` to download all your team workspaces, `run` to test your code locally, and `push` to upload changes to YepCode Cloud. Watch the video below for an overview of how YepCode CLI can be used ([Spanish version](https://www.youtube.com/watch?v=rlsTo6KIZak)): Note Video was recorded when it was needed to ask for access to install CLI. Right now is open to every YepCode user. ## Installation [Section titled “Installation”](#installation) YepCode CLI is published on [npmjs](https://www.npmjs.com/package/@yepcode/cli) so just install it as any other nodejs package: ```sh npm install -g @yepcode/cli ``` ## Usage [Section titled “Usage”](#usage) ### Ask for help [Section titled “Ask for help”](#ask-for-help) As with any other command-line tool, you can run the help command to display the list of available commands: ```sh $ yepcode help YepCode Command Line Interface VERSION @yepcode/cli/1.0 USAGE $ yepcode [COMMAND] COMMANDS clone Clone team processes help Display help for yepcode. login Login to the service logout Logout from service ... ``` ### Login to your YepCode account [Section titled “Login to your YepCode account”](#login-to-your-yepcode-account) Before interacting with your account, you need to log in. These credentials are personal and grant you access to your YepCode teams. ```sh $ yepcode login What is your yepcode email?: ada.lovelace@yepcode.io What is your yepcode password (not stored)?: ********** 🔑 Checking credentials... done 👐 Hi, Ada Lovelace! ``` Tip The cli uses a local folder `.yepcode` to store credentials and metadata. By default this folder is in your HOME directory, but you may configure it using the `YEPCODE_CONFIG_PATH` env variable. You can provide your credentials using the credentials prompt, or you can use the `--email` and `--password` options. ```sh $ yepcode login --email your-email --password your-password ``` Note We don’t yet support the external identity providers in YepCode CLI (Google Auth, Github or Microsoft). If you have used it to create your account, you need ask for a password reset and setup one: ![Screenshot](/docs/img/screenshots/reset-password.png) ### Logout from your YepCode account [Section titled “Logout from your YepCode account”](#logout-from-your-yepcode-account) Perform a logout to remove access to your YepCode account. ```sh $ yepcode logout 👋 Bye! ``` ### Clone your team workspace locally [Section titled “Clone your team workspace locally”](#clone-your-team-workspace-locally) Clone one of your team workspaces using: ```sh $ yepcode clone ada-lovelace fetching processes... fetching modules... fetching variables... 🎉 ada-lovelace team processes cloned successfully! $ cd ada-lovelace ``` Note If you don’t provide parameters to the `clone` command, you’ll see the list of available teams. ```sh $ yepcode clone 🏢 Allowed teams: ada-lovelace sandbox ``` Inspect the generated folder, and you’ll see some folders and files: ```plaintext 📦 ada-lovelace ┣ 📂 dependencies ┃ ┣ 📜 package.json ┃ ┣ 📜 requirements.txt ┣ 📂 modules ┃ ┣ 📂 ┃ ┃ ┗ 📜 .js ┃ ┣ 📂 ┃ ┃ ┗ 📜 .py ┃ ┣ 📂 ┃ ┃ ┣ 📂 versions ┃ ┃ ┃ ┣ 📂 v1.0 ┃ ┃ ┃ ┃ ┗ 📜 .js ┃ ┃ ┃ ┗ 📂 ... ┃ ┃ ┗ 📜 .js ┃ ┗ 📂 ... ┣ 📂 processes ┃ ┣ 📂 ┃ ┃ ┣ 📜 README.md ┃ ┃ ┣ 📜 index.js ┃ ┃ ┣ 📜 parametersSchema.json ┃ ┃ ┗ 📜 parameters.json ┃ ┣ 📂 ┃ ┃ ┣ 📜 README.md ┃ ┃ ┣ 📜 main.py ┃ ┃ ┣ 📜 parametersSchema.json ┃ ┃ ┗ 📜 parameters.json ┃ ┣ 📂 ┃ ┃ ┣ 📂 versions ┃ ┃ ┃ ┣ 📂 v1.0 ┃ ┃ ┃ ┃ ┣ 📜 README.md ┃ ┃ ┃ ┃ ┣ 📜 index.js ┃ ┃ ┃ ┃ ┣ 📜 parametersSchema.json ┃ ┃ ┃ ┃ ┗ 📜 parameters.json ┃ ┃ ┃ ┗ 📂 ... ┃ ┃ ┣ 📜 README.md ┃ ┃ ┣ 📜 index.js ┃ ┃ ┣ 📜 parametersSchema.json ┃ ┃ ┗ 📜 parameters.json ┃ ┗ 📂 ... ┣ 📜 datastore.json ┣ 📜 variables.env ┣ 📜 variables.local.env ┣ 📜 .gitignore ┗ 📂 .yepcode ``` * `dependencies`: Dependencies’ source code, containing both the python and javascript dependencies. * `package.json`: It will be a json file with the dependencies for the javascript dependencies. Just the content of the inner dependencies field in any standard package (do not include the `dependencies` field). Sample: ```json { "axios": "^1.6.0", "nodemailer": "^6.9.0" } ``` * `requirements.txt`: Python requirements.txt file with the dependencies for the python dependencies. Sample: ```txt datarobot==3.5.2 psycopg2-binary==2.9.10 ``` * `processes`: Processes’ source code, with one folder per process, containing process files. * `README.md`: Markdown file with the process description. * `index.js` or `index.py`: Process source code in JavaScript or Python. * `parametersSchema.json`: Parameters schema JSON file. * `parameters.json`: Sample input file dynamically generated. It will be used as default input file in local executions, but you may provide another one. * `versions`: if process has published versions, a new folder will exists and each version folder will have a process replica with the published contents. * `modules`: Modules’ source code, with one folder per module, containing the module file. * `versions`: if module has published versions, a new folder will exists and each version folder will have a module replica with the published contents. * `variables.env`: Includes all team variables in .env file format (KEY=VALUE). * `variables.local.env`: Local environment variables that override `variables.env`. * `datastore.json`: YepCode datastore file. * `.gitignore`: Auto generated gitignore file. It will be used if you create a git repo for this directory to ignore sensitive resources (variables .env). * `.yepcode`: YepCode workspace metadata directory. Note Variables won’t be filled, so for local execution testing, you must fill the values. The best option is to create the following local files which won’t be synced with remote: * `variables.local.env`: Local environment variables that override `variables.env` Caution `.yepcode` is a directory containing workspace metadata and is not meant to be edited by the user. ### Execute processes locally [Section titled “Execute processes locally”](#execute-processes-locally) Execute a process locally using the `run` command: ```sh $ yepcode run ``` Tip To see the list of available processes, use the `processes:status` command. By default, the process is executed using the `parameters.json` file located in the process folder. You may provide another input params using the `--parameters` option: ```sh $ yepcode run --parameters path/to/parameters.json ``` ### Run a local webhook server [Section titled “Run a local webhook server”](#run-a-local-webhook-server) The `http` command starts a local HTTP server that replicates the same webhook environment that YepCode provides on the cloud, exposing also your forms schema. This lets you develop and test webhook-triggered processes directly on your workstation without any deployments. ```sh $ yepcode http ``` Available flags: | Flag | Default | Description | | ----------------- | ------- | ---------------------------------------------------------------------- | | `-P, --port` | `3000` | Port to listen on | | `-l, --logLevel` | `DEBUG` | Log level for process executions (`DEBUG`, `INFO`, `WARNING`, `ERROR`) | | `--auth-user` | — | Basic auth username | | `--auth-password` | — | Basic auth password | | `-j, --jsonLogs` | — | Output process logs as NDJSON | ```sh # Start on default port 3000 $ yepcode http # Start on a custom port $ yepcode http --port 8080 # Protect the local server with basic auth $ yepcode http --auth-user admin --auth-password secret ``` ### Run integration tests [Section titled “Run integration tests”](#run-integration-tests) The `test` command lets you define and run test cases for your processes locally. Tests live alongside the process source code and verify that a process produces the expected output for a given set of inputs. Tip Integrate `yepcode test` into your CI/CD pipeline — it exits with code **0** when all tests pass and **1** when any fail, making it a drop-in step for any pipeline that checks exit codes. This is the most straightforward way to make your processes significantly more robust. #### Scaffold tests for a process [Section titled “Scaffold tests for a process”](#scaffold-tests-for-a-process) Use `test:scaffold` to generate a starter test structure for a process: ```sh $ yepcode test:scaffold my-process ``` #### Folder structure [Section titled “Folder structure”](#folder-structure) ```plaintext processes/ my-process/ index.js tests/ variables.test.env ← optional: variable overrides for all tests testHooks.js ← optional: global setup/teardown hooks 01-basic/ input.json ← required: parameters passed to the process output.json ← optional: expected return value variables.test.env ← optional: variable overrides for this test only testHooks.js ← optional: per-test setup/teardown hooks 02-edge-case/ input.json output.json 03-invalid-input/ input.json error.json ← optional: expected failure (mutually exclusive with output.json) ``` Test cases are discovered by scanning subdirectories of `tests/` and run in alphabetical order — use a numeric prefix (`01-`, `02-`, …) to control the sequence. #### Running tests [Section titled “Running tests”](#running-tests) ```sh # Run tests for all processes in the workspace $ yepcode test # Run tests for a single process $ yepcode test my-process # Show full process log output during test runs $ yepcode test --logLevel DEBUG my-process ``` #### Input and output files [Section titled “Input and output files”](#input-and-output-files) **`input.json`** — passed as `yepcode.context.parameters` to the process, exactly like `--parameters` on `yepcode run`: ```json { "userId": 42, "format": "csv" } ``` **`output.json`** — the expected return value. Comparison is exact deep equality — every key must match. If omitted, the test only checks that the process runs without throwing (smoke test): ```json { "rows": 5, "status": "ok" } ``` **`error.json`** — use instead of `output.json` when the process is *expected* to fail. `output.json` and `error.json` are mutually exclusive: ```json {} ``` ```json { "message": "User not found" } ``` An empty object asserts only that the process fails. Adding a `"message"` key asserts the error message contains that substring (case-sensitive). #### Variable overrides [Section titled “Variable overrides”](#variable-overrides) Variables are resolved in the following priority order (highest wins): 1. Per-test `tests/{name}/variables.test.env` 2. Global `tests/variables.test.env` 3. Workspace `.env.local` 4. Workspace `.env` ```sh # tests/variables.test.env — override DB for all tests DB_URL=postgres://localhost/test_db ``` ```sh # tests/02-auth-check/variables.test.env — override for one specific test API_KEY=test-only-key ``` #### Hooks [Section titled “Hooks”](#hooks) Hooks let you seed data, reset state, or clean up external resources around test execution. Export `before`, `after`, or both from a `testHooks.js` (or `testHooks.py`) file. Inside hooks you have full access to `yepcode.env`, `yepcode.datastore`, `yepcode.processes`, and all other SDK features. * **Global hooks** (`tests/testHooks.js`) run once around the entire suite — `before` before the first test, `after` after the last. * **Per-test hooks** (`tests/{name}/testHooks.js`) run around each individual test. tests/testHooks.js (JavaScript) ```js module.exports.before = async function before() { await yepcode.datastore.set('counter', '0') } module.exports.after = async function after() { await yepcode.datastore.del('counter') } ``` tests/testHooks.py (Python) ```python def before(): yepcode.datastore.set("counter", "0") def after(): yepcode.datastore.del_("counter") ``` Note If a global `before` hook fails, all tests in the suite are marked as failed and skipped. If a per-test `before` hook fails, only that test is marked as failed; subsequent tests still run. `after` hooks always run regardless of the test result and their failure does not affect the test outcome. #### Test output [Section titled “Test output”](#test-output) ```plaintext Testing my-process (3 tests) ✓ 01-basic (245ms) ✓ 02-edge-case (312ms) ✗ 03-error-path Expected: {"status":"error"} Received: {"status":"ok","message":"unexpected success"} 2 passed, 1 failed ──────────────────────────────────────────────── Total: 3 tests — 2 passed, 1 failed ``` ### Manage package dependencies [Section titled “Manage package dependencies”](#manage-package-dependencies) YepCode support custom dependencies to use any npmjs or pypi package in your processes. Check [dependencies section](/docs/dependencies) for more information. In order to run a process, you need to install your team configured dependencies. You can do that with the `dependencies` command: ```sh $ yepcode dependencies [all|javascript|python] ``` There are two flags to manage dependencies: * `--check`: Check if dependencies are installed and installed versions are up to date. * `--reset`: Performs a full reinstall of configured dependencies. Tip By default, dependencies are installed inside `~/.yepcode/dependencies`, but remember that you may configure this using the `YEPCODE_CONFIG_PATH` env variable. ### Pull changes from cloud [Section titled “Pull changes from cloud”](#pull-changes-from-cloud) If you or your colleages have performed changes in YepCode cloud, update your local files. Fetch all processes from cloud and save them locally: ```sh $ yepcode pull fetching processes... - [new] -> Create process name () - [updated] -> Updated process name () - [deleted] -> Deleted process name () modules are up to date. variables are up to date. ``` Tip If you or your team have modified process both locally and in the cloud, the CLI prompts you on how to resolve conflicts: ```sh 🔥 conflictive-process-name () has been modified both remote and local! Do you want to override local changes? yes/no: ``` ### Push changes to cloud [Section titled “Push changes to cloud”](#push-changes-to-cloud) After upgrading your processes or modules locally, update your cloud workspace from local changes using `push` command. ```sh $ yepcode push uploading processes... [uploaded] -> modified-process-name () uploaded to remote. [overwritten] -> conflictive-process-name () overwritten in remote. ``` Tip If you or your team have modified processes both locally and in the cloud, CLI prompts you on how to resolve conflicts: ```sh 🔥 conflictive-process-name () has been modified both origin and local! Do you want force push to origin? yes/no: ``` ### Add local created resources [Section titled “Add local created resources”](#add-local-created-resources) If you have created resources on your local workspace, you can add them to keep track and after that they could be pushed to remote: ```plaintext ℹ️ 1 processes only existing in local: a-new-local-process Use command 'yepcode processes:add' to keep track of these resources ``` Using the `yepcode processes:add` command, it will be added and then will be shown in the status log. ### Add new remote cloud team [Section titled “Add new remote cloud team”](#add-new-remote-cloud-team) YepCode CLI is able to work with multiple remotes. This is pretty interesting to keep sync processes or modules between those environments. Let’s say that you have a YepCode staging enviroment where you test your code before going to production. You cloud clone the staging environment and then add a new remote for the production envinroment. This is done with the `yepcode remote` command: ```sh $ yepcode remote Add a remote team workspace USAGE $ yepcode remote:COMMAND COMMANDS remote:add Add a remote team workspace remote:set Set the active remote team workspace ``` After adding a new remote, it may be needed to perform a `yepcode add` just to keep track of the files in this new environment. After that, you could go with a `yepcode push` to deploy changes to the cloud. ### Resource topics [Section titled “Resource topics”](#resource-topics) Each workspace resource has a dedicated topic, allowing you to manage your workspace resources independently using topics (modules, processes, variables): | Topic/Command | status | pull | push | | ------------- | -------------------- | -------------------- | ------------------------ | | processes | :white\_check\_mark: | :white\_check\_mark: | :white\_check\_mark: | | modules | :white\_check\_mark: | :white\_check\_mark: | :white\_check\_mark: | | variables | :white\_check\_mark: | :white\_check\_mark: | :sparkles: (just create) | #### List resources [Section titled “List resources”](#list-resources) You may list all available resources using the `status` command: ```sh $ yepcode processes:status processes status: slug name status ────────────────────────────── ────────────────────────────────── ──────────────── hello-world Hello world ✅ (up-to-date) stripe-customers-from-supabase Stripe Customers From Supabase Bar ✅ (up-to-date) ``` #### Pull resources changes from cloud [Section titled “Pull resources changes from cloud”](#pull-resources-changes-from-cloud) In addition, you can fetch resources from the cloud and update locally: ```sh $ yepcode processes:pull fetching processes... processes are up to date. ``` #### Push resources changes to cloud [Section titled “Push resources changes to cloud”](#push-resources-changes-to-cloud) You can update cloud resources with local changes: ```sh $ yepcode modules:push updating modules... modules up-to-date ``` Note If you or your team have modified processes both locally and in the cloud, the CLI prompts you on how to resolve conflicts using both `pull` and `push` commands ### Debug with visual studio code [Section titled “Debug with visual studio code”](#debug-with-visual-studio-code) You can debug your yepcode processes using `vscode`. In order to have full debugging support you need to encapsulate your code in a main() function: javascript example ```js const { yepcode } = require('yepcode'); async function main() { // your code } module.exports = { main }; ``` python example ```python from yepcode import yepcode, logger def main(): # your code ``` Note If you try to debug a process without a main() function, you’ll get a warning message: Javascript warning message ```sh ############################################################################################ ### WARNING!!: Process does not cointain a main() function, breakpoints will not work. ### ### You should encapsulate your code in a main() function for full debugging support. ### ############################################################################################ ### // Sample process code: ### ### ### ### const { yepcode } = require("yepcode"); ### ### async function main() { ### ### // your code ### ### } ### ### module.exports = { main } ### ### ### ############################################################################################ ``` Python warning message ```sh ############################################################################################ ### WARNING!!: Process does not cointain a main() function, breakpoints will not work. ### ### You should encapsulate your code in a main() function for full debugging support. ### ############################################################################################ ### // Sample process code: ### ### ### ### from yepcode import yepcode, logger ### ### def main(): ### ### // your code ### ### ### ############################################################################################ ``` Then you need to create the vscode configuration files. You can do it with the `setup-debug` command: ```sh $ yepcode setup-debug ✨ Created .vscode/launch.json ✨ Created .vscode/settings.json ``` Note If you rerun this command or already have the vscode configuration files `.vscode/launch.json` / `.vscode/settings.json`, you’ll be asked to overwrite the existing files: ```sh $ yepcode setup-debug ✔ ⚠️ File .vscode/launch.json already exists. Do you want to overwrite it? yes/no Yes ✨ Created .vscode/launch.json ✔ ⚠️ File .vscode/settings.json already exists. Do you want to overwrite configuration? yes/no Yes ✨ Updated .vscode/settings.json ``` Now in your vscode `Run and Debug` tab you can select which process you want to debug: ![Screenshot](/docs/img/screenshots/debug-vscode.png) * The first two entries will debug your current file, you need to select Python/Node Debugger option depending on the language of your process. * Next entries will be your processes, you can select one of them to debug. Caution If you create/delete a process, `yepcode setup-debug` command should be reruned in order to update the vscode debug configuration files. Then the process will be added/removed from the debug selector options. ## Update CLI [Section titled “Update CLI”](#update-cli) If you want to update the CLI, you can do it using the `npm install` command: ```sh $ npm install -g @yepcode/cli ``` If a new version is available, you will be notified to update the CLI. ```sh $ yepcode --version __ __ _____ _ \ \ / / / ____| | | \ \_/ /__ _ __ | | ___ __| | ___ \ / _ \ '_ \| | / _ \ / _` |/ _ \ | | __/ |_) | |___| (_) | (_| | __/ |_|\___| .__/ \_____\___/ \__,_|\___| | | |_| Update available x.y.z → X.Y.Z Run `npm i -g @yepcode/cli` to update @yepcode/cli/x.y.z darwin-x64 node-v16.x.x ``` # Network Access > Learn how to enable network access for YepCode integrations to connect with your private services. When using YepCode with a service that is not accessible from the internet, such as a Postgres server on your internal infrastructure or a REST API behind a firewall, you need to configure access to allow YepCode servers to connect. ## Configure Your Firewall for YepCode Access [Section titled “Configure Your Firewall for YepCode Access”](#configure-your-firewall-for-yepcode-access) Configure your firewalls to allow connections from the IP **34.89.54.108** for the required ports. This step ensures that YepCode integrations function seamlessly. If altering your company’s firewall rules is not feasible, we offer an alternative solution: tunneling. ## YepCode Tunneling [Section titled “YepCode Tunneling”](#yepcode-tunneling) We provide a tunneling system that exposes your ports for YepCode using [SSH tunnels](https://www.ssh.com/academy/ssh/tunneling). With this approach, you start an agent on your network and then you configure the tunnel as destination from your YepCode credentials. This deployment option is only available on paid plans, so please [contact us](https://yepcode.io/contact/) if you are interested in using this. ## When using MCP tools [Section titled “When using MCP tools”](#when-using-mcp-tools) If your MCP tools (or processes invoked via MCP) call services behind a firewall or on private infrastructure: * Use the **IP allowlist** — Allow YepCode’s IP so executions can reach your services * Use **tunneling** — If firewall changes are not possible, configure tunneling so YepCode can connect to your network See the [MCP server README](https://github.com/yepcode/mcp-server-js) for debugging and troubleshooting. # YepCode Core Concepts Rules > Essential guide to YepCode platform architecture and core concepts. Covers processes, modules, execution context, team variables, datastore, workspace structure, and development best practices for building enterprise-grade integrations and automations. Essential guide to YepCode platform architecture and core concepts. Covers processes, modules, execution context, team variables, datastore/storage, workspace structure, and best practices for building robust integrations and automations. [Download this file](/docs/ai-rules.md) ## What is YepCode? [Section titled “What is YepCode?”](#what-is-yepcode) YepCode is an enterprise-ready integration and automation platform that offers comprehensive features for API integrations, workflow automation, and data processing. It excels in providing enterprise-grade sandboxing and security measures specifically designed for running code generated by LLMs. This offers developers a familiar coding environment, while handling all the infrastructure concerns, security measures, and dependency management automatically. ## Quick Reference [Section titled “Quick Reference”](#quick-reference) ### Key Concepts at a Glance [Section titled “Key Concepts at a Glance”](#key-concepts-at-a-glance) | Concept | Description | Key point | | ------------- | --------------------------------- | ----------------------------------------- | | **Process** | Executable unit of business logic | Has input parameters, returns results | | **Module** | Reusable code library | Shared across processes, can be versioned | | **Variables** | Configuration & secrets | Use env vars; never hardcode secrets | | **Datastore** | Persistent key-value store | **Strings and numbers only** | | **Storage** | File storage | Use for binary files and documents | ### Runtime Versions [Section titled “Runtime Versions”](#runtime-versions) | Language | Runtime | | -------------- | ----------- | | **JavaScript** | Node.js v22 | | **Python** | v3.13 | ## Core Concepts [Section titled “Core Concepts”](#core-concepts) ### Processes [Section titled “Processes”](#processes) * **What it is**: The basic unit of execution in YepCode. * **Languages**: JavaScript (Node.js v22) or Python (v3.13). * **Parameters**: Processes may define input parameters via JSON Schema (`parametersSchema.json`) and access them through `yepcode.context.parameters`. * **Return values**: Return structured JSON for results; for webhook-style responses, return `{ status, headers, body }` when applicable. ### Workspace Structure (CLI) [Section titled “Workspace Structure (CLI)”](#workspace-structure-cli) If you use the YepCode CLI, your local workspace commonly looks like this: ```plaintext 📦 ┣ 📂 dependencies ┃ ┣ 📜 package.json ┃ ┣ 📜 requirements.txt ┣ 📂 modules ┃ ┣ 📂 ┃ ┃ ┗ 📜 .js ┃ ┣ 📂 ┃ ┃ ┗ 📜 .py ┃ ┣ 📂 ┃ ┃ ┣ 📂 versions ┃ ┃ ┃ ┣ 📂 v1.0 ┃ ┃ ┃ ┃ ┗ 📜 .js ┃ ┃ ┃ ┗ 📂 ... ┃ ┃ ┗ 📜 .js ┃ ┗ 📂 ... ┣ 📂 processes ┃ ┣ 📂 ┃ ┃ ┣ 📜 README.md ┃ ┃ ┣ 📜 index.js ┃ ┃ ┣ 📜 parametersSchema.json ┃ ┃ ┣ 📜 parameters.json ┃ ┃ ┗ 📜 package.json (process scoped dependencies) ┃ ┣ 📂 ┃ ┃ ┣ 📜 README.md ┃ ┃ ┣ 📜 main.py ┃ ┃ ┣ 📜 parametersSchema.json ┃ ┃ ┣ 📜 parameters.json ┃ ┃ ┗ 📜 requirements.txt (process scoped dependencies) ┃ ┣ 📂 ┃ ┃ ┣ 📂 versions ┃ ┃ ┃ ┣ 📂 v1.0 ┃ ┃ ┃ ┃ ┣ 📜 README.md ┃ ┃ ┃ ┃ ┣ 📜 index.js ┃ ┃ ┃ ┃ ┣ 📜 parametersSchema.json ┃ ┃ ┃ ┃ ┗ 📜 parameters.json ┃ ┃ ┃ ┗ 📂 ... ┃ ┃ ┣ 📜 README.md ┃ ┃ ┣ 📜 index.js ┃ ┃ ┣ 📜 parametersSchema.json ┃ ┃ ┗ 📜 parameters.json ┃ ┗ 📂 ... ┣ 📜 datastore.json ┣ 📜 variables.env ┣ 📜 variables.local.env ┣ 📜 .gitignore ┗ 📂 .yepcode ``` Key folders/files: * **`dependencies/`**: Shared dependencies source configuration. * **`package.json`**: JavaScript dependencies (the inner `dependencies` object only). Example: ```json { "axios": "^1.6.0", "nodemailer": "^6.9.0" } ``` * **`requirements.txt`**: Python dependencies. Example: ```txt datarobot==3.5.2 psycopg2-binary==2.9.10 ``` * **`processes/`**: One folder per process (code, parameters schema, test parameters, README). * **`modules/`**: One folder per module (reusable libraries). * **`variables.env`**: Team variables in `.env` format (`KEY=VALUE`). * **`variables.local.env`**: Local overrides (not shared). * **`datastore.json`**: Datastore contents (if exported by tooling). ### Modules [Section titled “Modules”](#modules) Modules are reusable code libraries shared across processes. Use modules to: * Avoid duplication (DRY) * Encapsulate API clients / integrations * Keep process code small and readable * Support versioning for stable interfaces **Module file naming (required):** Each module must live in a folder named after the module slug, with the entry file named the same: `modules//.js` (JavaScript) or `modules//.py` (Python). Do **not** use `index.js` or `main.py` for modules—those names are only for process entry files. Example: `modules/shopify-client/shopify-client.js` ✅; `modules/shopify-client/index.js` ❌. ### Execution Context [Section titled “Execution Context”](#execution-context) Each process runs in an isolated environment and has access to: * **Input parameters**: `yepcode.context.parameters` * **Environment variables**: `process.env.*` / `os.getenv(...)` (or `yepcode.env.*`) * **Execution metadata**: `yepcode.execution.*` * **Request data** (webhooks): request body/headers (when applicable) ### Variables (Configuration & Secrets) [Section titled “Variables (Configuration & Secrets)”](#variables-configuration--secrets) * Store configuration (base URLs, timeouts) and secrets (API keys, tokens) as variables. * **Never hardcode secrets** in code or commit them to source control. * **Never log secrets** (mask or omit them from logs). * When editing variable files (e.g. `variables.env`), **do not overwrite the entire file** when adding or updating a variable. Read the file first and add or update only the specific variable(s) so existing variables are not removed. ### Datastore [Section titled “Datastore”](#datastore) Datastore is a persistent key-value store for maintaining state across runs. * **Great for**: last-run timestamps, cursors, deduplication IDs, caches. * **Critical limitation**: can only store **strings** and **numbers**. Serialize objects to JSON first. ### Storage [Section titled “Storage”](#storage) Storage is for files (binary or large payloads) that don’t belong in datastore. * **Great for**: reports, exported files, images, PDFs, data extracts. ## Decision Guidelines [Section titled “Decision Guidelines”](#decision-guidelines) ### When to Create a Module vs Inline Code [Section titled “When to Create a Module vs Inline Code”](#when-to-create-a-module-vs-inline-code) | Scenario | Recommendation | | ------------------------------------- | ----------------------------------- | | API client used by multiple processes | ✅ Create a module | | Utility helpers used 2+ times | ✅ Create a module | | One-off transformation | ❌ Keep inline | | Complex logic only used once | ❌ Keep inline (unless it will grow) | ### When to Use Datastore vs Variables vs Storage [Section titled “When to Use Datastore vs Variables vs Storage”](#when-to-use-datastore-vs-variables-vs-storage) | Need | Use | | --------------------------------- | ----------------------------- | | Configuration that rarely changes | **Variables** | | Secrets / credentials | **Variables** | | State that changes between runs | **Datastore** | | Caching API responses | **Datastore** (mind size/TTL) | | Binary files / large exports | **Storage** | ## Naming Conventions [Section titled “Naming Conventions”](#naming-conventions) | Resource | Convention | Example | | -------------------- | ---------------------- | -------------------- | | Process slug | kebab-case | `order-sync-shopify` | | Module slug | kebab-case | `shopify-client` | | Variables | SCREAMING\_SNAKE\_CASE | `SHOPIFY_API_KEY` | | JavaScript functions | camelCase | `fetchOrders()` | | Python functions | snake\_case | `fetch_orders()` | ## General Rules (Always Follow) [Section titled “General Rules (Always Follow)”](#general-rules-always-follow) * **Validate inputs early**: check required parameters and types at the start. * **Handle errors explicitly**: throw meaningful, actionable errors. * **Use timeouts/retries** for external calls; be mindful of rate limits. * **Log key steps** (start/end, major decisions, external calls) but **never log secrets**. * **Avoid hardcoded values**: prefer parameters or variables. * **Keep outputs structured**: return JSON that is easy to consume and debug. # YepCode JavaScript Code Rules > This file provides guidelines for LLMs to write JavaScript code compatible with the YepCode platform and ready to use it's specific helpers. This file provides guidelines for LLMs to write JavaScript code compatible with YepCode platform and ready to use its specific helpers. [Download this file](/docs/ai-rules/code/javascript.md) ## JavaScript Code Rules [Section titled “JavaScript Code Rules”](#javascript-code-rules) ## Quick Reference [Section titled “Quick Reference”](#quick-reference) | Aspect | Guideline | | ----------------------- | ---------------------------------- | | **Runtime** | Node.js v22 | | **Main file (process)** | `index.js` | | **Entry point** | `async function main()` | | **Export (required)** | `module.exports = { main }` | | **Parameters** | `yepcode.context.parameters` | | **Variables** | `process.env.X` or `yepcode.env.X` | | **Modules** | `yepcode.import("module-slug")` | ### Critical Rules [Section titled “Critical Rules”](#critical-rules) * ✅ **Always** export `main` with `module.exports = { main }` * ❌ **Never** call `main()` directly * ✅ **Always** use `async/await` for async operations * ✅ **Always** add `try/catch` around the main flow for actionable errors * ❌ **Never** use dynamic module names with `yepcode.import()`—module names must be **hardcoded strings** (e.g. `yepcode.import("module-name")`), not variables * ✅ Use **const** or **let**; avoid **var** ## Process Template [Section titled “Process Template”](#process-template) ```javascript async function main() { // Access input parameters const { parameters } = yepcode.context; // Your code here // Return result return { message: "Success!" }; } module.exports = { main }; ``` ## Helpers Usage [Section titled “Helpers Usage”](#helpers-usage) * Access execution info: `const { id, comment } = yepcode.execution;` * Access process info: `const { id: processId, name: processName } = yepcode.execution.process;` * Access schedule info (if present): `const { id: scheduleId, comment: scheduleComment } = yepcode.execution.schedule;` * Access team timezone: `const timezone = yepcode.execution.timezone;` * Use environment variables: `const apiKey = process.env.API_KEY; // or yepcode.env.API_KEY` * Import YepCode modules: `const { myFunc } = yepcode.import("module-name");` * Caution: module names must be **hardcoded strings** (no variables) * Import with version: `const { myFunc } = yepcode.import("module-name", "v1.0");` * Run another process: `await yepcode.processes.run("process-identifier", options);` ## Logging [Section titled “Logging”](#logging) ```javascript console.log("INFO message"); console.debug("DEBUG message"); console.info("INFO message"); console.warn("WARNING message"); console.error("ERROR message"); ``` ## Dependencies Management [Section titled “Dependencies Management”](#dependencies-management) * You may use external npm packages * Just add the require statement to the code and the package will be installed automatically * If package import name is different than the package name, you must use the `@add-package` comment: ```javascript // @add-package axios const axios = require("axios"); ``` ## Local Disk [Section titled “Local Disk”](#local-disk) ```javascript const path = require("path"); // Calculate the path to the temporary file const filePath = path.join(process.env.TMP_DATA_DIR, "myfile.txt"); // Writing a file const fs = require("fs"); fs.writeFileSync(filePath, "Hello from YepCode!"); ``` ## Datastore [Section titled “Datastore”](#datastore) ```js // Setting a value await yepcode.datastore.set("key", "value"); // Setting a object value await yepcode.datastore.set("key", JSON.stringify({ name: "John", age: 30 })); // Getting a value const value = await yepcode.datastore.get("key"); // Deleting a value await yepcode.datastore.del("key"); ``` ## Storage [Section titled “Storage”](#storage) ```js const fs = require("node:fs"); const path = require("node:path"); const localPath = path.join(process.env.TMP_DATA_DIR, "localfile.txt"); // Uploading a file await yepcode.storage.upload("path/myfile.txt", fs.createReadStream(localPath)); // Listing files const files = await yepcode.storage.list(); // Downloading a file const stream = await yepcode.storage.download("path/myfile.txt"); stream.pipe(fs.createWriteStream(localPath)); // Deleting a file await yepcode.storage.delete("path/myfile.txt"); ``` ## Return Values [Section titled “Return Values”](#return-values) ### Standard Return [Section titled “Standard Return”](#standard-return) ```javascript return { message: "Success!" }; ``` ### Custom HTTP Status Codes [Section titled “Custom HTTP Status Codes”](#custom-http-status-codes) * This is the format for custom HTTP status codes: ```javascript return { status: 404, body: { message: "Not found" }, headers: { "Content-Type": "application/json" } }; ``` ## Transient Results [Section titled “Transient Results”](#transient-results) ```javascript return { transient: true, data: sensitiveData, }; ``` ## Do & Don’t [Section titled “Do & Don’t”](#do--dont) **Do** * Export `main` with `module.exports = { main }`. * Use async/await for asynchronous work. * Validate parameters at the start; throw clear errors for missing or invalid input. * Use environment variables (e.g. `process.env.API_KEY`) for secrets; never hardcode them. * Use try/catch around the main flow and log or re-throw with clear messages. * Log important steps; never log secrets. **Don’t** * Never call `main()` in your code—YepCode invokes it. * Never hardcode API keys, passwords, or tokens. * Don’t forget to export: `module.exports = { main }`. * Don’t use **var**; use **const** or **let**. * Don’t ignore errors; wrap risky operations in try/catch. * Don’t use dynamic module names: `yepcode.import(moduleName)` is wrong; use `yepcode.import("module-name")`. # YepCode Python Code Rules > This file provides guidelines for LLMs to write Python code compatible with YepCode platform and ready to use its specific helpers. This file provides guidelines for LLMs to write Python code compatible with YepCode platform and ready to use its specific helpers. [Download this file](/docs/ai-rules/code/python.md) ## Python Code Rules [Section titled “Python Code Rules”](#python-code-rules) ## Quick Reference [Section titled “Quick Reference”](#quick-reference) | Aspect | Guideline | | ----------------------- | -------------------------------------- | | **Runtime** | Python 3.13 | | **Main file (process)** | `main.py` | | **Entry point** | `def main()` | | **Parameters** | `yepcode.context.parameters` | | **Variables** | `os.getenv("X")` or `yepcode.env.X` | | **Modules** | `yepcode.import_module("module-slug")` | ### Critical Rules [Section titled “Critical Rules”](#critical-rules) * ✅ **Always** define a `main()` function * ❌ **Never** call `main()` directly * ✅ **Always** add `try/except` around the main flow for actionable errors * ✅ Follow **PEP 8** (and add type hints when useful) * ✅ **Always** use **snake\_case** for variables and functions * ❌ **Never** use dynamic module names with `yepcode.import_module()`—module names must be **hardcoded strings** (e.g. `yepcode.import_module("module-name")`), not variables ## Process Template [Section titled “Process Template”](#process-template) ```python def main(): # Access input parameters parameters = yepcode.context.parameters # Your code here # Return result return { "message": "Success!" } ``` ## Helpers Usage [Section titled “Helpers Usage”](#helpers-usage) * Access execution info: `execution_id = yepcode.execution.id` * Access process info: `process_id = yepcode.execution.process.id` * Access schedule info (if present): `scheduleId, scheduleComment = yepcode.execution.schedule.id, yepcode.execution.schedule.comment` * Access team timezone: `timezone = yepcode.execution.timezone` * Use environment variables: `api_key = os.getenv("API_KEY") # or yepcode.env.API_KEY` * Import YepCode modules: `client = yepcode.import_module("module-name")` * Caution: module names must be **hardcoded strings** (no variables) * Import with version: `client = yepcode.import_module("module-name", "v1.0")` * Run another process: `yepcode.processes.run("process-identifier", options)` ## Logging [Section titled “Logging”](#logging) ```python print("INFO message") # Generates INFO level log logger.debug("DEBUG message") logger.info("INFO message") logger.warn("WARNING message") logger.error("ERROR message") ``` ## Dependencies Management [Section titled “Dependencies Management”](#dependencies-management) * You may use external pip packages. * Just add the `import` statement and the package will be installed automatically. * If the **package name** differs from the **import name**, use the `@add-package` comment: ```python # @add-package requests import requests ``` ## Local Disk [Section titled “Local Disk”](#local-disk) ```python import os # Calculate the path to the temporary file file_path = os.path.join(os.environ.get("TMP_DATA_DIR"), "myfile.txt") # Writing a file with open(file_path, 'w') as f: f.write('Hello from YepCode!') ``` ## Datastore [Section titled “Datastore”](#datastore) ```python import json # Setting a value yepcode.datastore.set("key", "value") # Setting a object value yepcode.datastore.set("key", json.dumps({ "name": "John", "age": 30 })) # Getting a value value = yepcode.datastore.get("key") # Deleting a value yepcode.datastore.delete("key") ``` ## Storage [Section titled “Storage”](#storage) ```python import os local_path = os.path.join(os.environ.get("TMP_DATA_DIR"), "localfile.txt") # Uploading a file with open(local_path, "rb") as f: obj = yepcode.storage.upload("path/myfile.txt", f) print("Uploaded:", obj.name, obj.size, obj.link) # Listing files objects = yepcode.storage.list() # Downloading a file content = yepcode.storage.download("path/myfile.txt") with open(local_path, "wb") as f: f.write(content) # Deleting a file yepcode.storage.delete("path/myfile.txt") ``` ## Return Values [Section titled “Return Values”](#return-values) ### Standard Return [Section titled “Standard Return”](#standard-return) ```python return { "message": "Success!" } ``` ### Custom HTTP Status Codes [Section titled “Custom HTTP Status Codes”](#custom-http-status-codes) * This is the format for custom HTTP status codes: ```python return { "status": 404, "body": { "message": "Not found" }, "headers": { "Content-Type": "application/json" } } ``` ## Transient Results [Section titled “Transient Results”](#transient-results) ```python return { "transient": True, "data": sensitive_data } ``` ## Do & Don’t [Section titled “Do & Don’t”](#do--dont) **Do** * Define `main()` and avoid calling it directly. * Validate parameters at the start; raise meaningful errors for missing or invalid input. * Use environment variables (e.g. `os.getenv("API_KEY")`) for secrets; never hardcode them. * Use try/except around the main flow and log or re-raise with clear messages. * Use **snake\_case** for variables and functions; follow PEP 8. * Use type hints where helpful. * Log important steps; never log secrets. **Don’t** * Never call `main()` in your code—YepCode invokes it. * Never hardcode API keys, passwords, or tokens. * Don’t use **camelCase** in Python; use snake\_case. * Don’t ignore errors; wrap risky operations in try/except. * Don’t use dynamic module names: `yepcode.import_module(module_name)` is wrong; use `yepcode.import_module("module-name")`. * Don’t rely on global variables for state; pass state through parameters or return values. # JSON Schema Sample > This is a sample JSON schema that includes all the available types of inputs supported by YepCode. This file provides guidelines for LLMs to write JSON schemas compatible with YepCode platform input parameters schema. [Download this file](/docs/ai-rules/code/json-schema-sample.md) ```json { "title": "Full [yepcode forms](https://yepcode.io) form sample", "description": "This is a sample form specification showing all available attribute types for [yepcode forms](https://yepcode.io)", "type": "object", "properties": { "oneStringField": { "title": "![alt text](https://yepcode.io/logo.svg) *[yepcode](https://yepcode.io)* form title", "description": "Visit [yepcode](https://yepcode.io) form description", "type": "string" }, "onePasswordField": { "title": "One password field", "type": "string", "description": "Password shoul be: \n 1. At least 12 characters long \n 2. Include a combination of uppercase and lowercase letters \n 3. At least one special character such as @, #, $, %", "isSensitive": true, "ui": { "ui:placeholder": "Use a secure password" } }, "oneHiddenField": { "title": "One hidden field", "type": "string", "ui": { "ui:widget": "hidden" } }, "oneIntegerField": { "title": "One integer field with range", "description": "Values must be between 0 and 500", "type": "integer", "minimum": 0, "maximum": 500 }, "oneBooleanField": { "title": "One boolean field with [link](https://yepcode.io)", "type": "boolean" }, "oneEmailField": { "title": "One email field", "type": "string", "format": "email" }, "oneTextAreaField": { "title": "One textarea field", "type": "string", "description": "> Block quote description", "ui": { "ui:widget": "textarea" } }, "oneColorField": { "title": "One color field", "type": "string", "ui": { "ui:widget": "color" } }, "oneFileField": { "title": "One file field", "type": "string", "ui": { "ui:widget": "file" } }, "oneObjectField": { "title": "One object field", "description": "This sample has two nested fields.", "required": [ "anotherString", "anotherInteger" ], "type": "object", "properties": { "anotherString": { "type": "string" }, "anotherInteger": { "type": "number", "minimum": -180, "maximum": 180 } } }, "oneStringArrayField": { "title": "One string array field", "type": "array", "items": { "type": "string" } }, "oneObjectsArrayField": { "title": "One object array field", "type": "array", "items": { "type": "object", "properties": { "oneProperty": { "description": "One property", "type": "string" }, "anotherProperty": { "description": "Another property", "type": "string" } } } }, "oneRadioField": { "title": "One string radio field", "type": "string", "ui": { "ui:widget": "radio" }, "oneOf": [ { "const": "option-1", "title": "Option 1 Label" }, { "const": "option-2", "title": "Option 2 Label" }, { "const": "option-3", "title": "Option 3 Label" } ] }, "oneCheckboxField": { "title": "One string checkboxes field", "type": "array", "ui": { "ui:widget": "checkboxes" }, "items": { "type": "string", "enum": [ "option 1", "option 2", "option 3" ] }, "uniqueItems": true }, "oneSelectField": { "title": "One string select field", "type": "string", "ui": { "ui:placeholder": "Pick one option" }, "enum": [ "option 1", "option 2", "option 3" ] }, "oneJsonParameter": { "title": "A JSON field", "description": "Block quote description", "type": "object", "ui": { "ui:field": "json" } }, "anotherBooleanField": { "title": "A input that shows other inputs", "type": "boolean" } }, "dependencies": { "anotherBooleanField": { "oneOf": [ { "properties": { "anotherBooleanField": { "enum": [ true ] }, "aDependencyValueProperty": { "title": "This is shown when anotherBooleanField is true", "type": "string" } } }, { "properties": { "anotherBooleanField": { "enum": [ false ] }, "aDependencyValueProperty": { "title": "This is shown when anotherBooleanField is false", "type": "string" } } } ] } }, "required": [ "oneStringField" ] } ``` # YepCode Agent Rules > Comprehensive guidelines for AI agents to create YepCode processes and modules through an iterative, confirmation-driven workflow. Includes planning phases, implementation strategies, error handling, and best practices for building integrations and automations. Comprehensive guidelines for AI agents to create YepCode processes and modules through an iterative, confirmation-driven workflow. Includes planning phases, implementation strategies, error handling, and best practices for building integrations and automations. [Download this file](/docs/ai-rules/agent.md) ## Agent Rules [Section titled “Agent Rules”](#agent-rules) You are a helpful assistant responsible for solving tasks through code generation and execution using YepCode and it’s MCP tools in an iterative, confirmation-driven approach. ## Core Principles [Section titled “Core Principles”](#core-principles) * **Explain before acting**: Describe what you’re going to do and why. * **Confirm before changing**: Get explicit approval before making significant or potentially destructive changes (code refactors, dependency changes, variable changes). * **Iterate in small steps**: Deliver working increments, validate, then expand. * **Be safe by default**: Never hardcode or log secrets. ## Workflow [Section titled “Workflow”](#workflow) ### Phase 1: Planning & Confirmation [Section titled “Phase 1: Planning & Confirmation”](#phase-1-planning--confirmation) Before writing any code, using any tool, or making changes, produce a short plan and confirm it with the user. 1. **Analyze Current Context** Review currently available YepCode context: * **Process language**: Check whether the process is JavaScript (`index.js`) or Python (`main.py`). Any new or updated code and modules must use the same language. * **Script**: Analyze what the current script is doing to guide the user toward a better solution. * **Variables**: Analyze which variables the user has defined; avoid removing or overwriting them when adding new ones. * **Dependencies**: Analyze which dependencies the user has defined. * **Modules**: Analyze which YepCode modules the user has defined for reuse. Remember module files must be named `/.js` or `/.py`, not `index.js` or `main.py`. 2. **Identify Implementation Alternatives** Carefully review the user’s task and identify all possible approaches: * **Service vs Direct Implementation**: For common tasks (email, SMS, payments, etc.), ask if they want to use: * A third-party service (e.g., SendGrid, Twilio, Stripe) * Direct protocol implementation (e.g., SMTP, HTTP APIs) * **Library Choices**: When multiple libraries can solve the same problem, present options with pros/cons * **Architecture Patterns**: For complex workflows, offer different architectural approaches * **Examples of questions to ask**: * “For sending emails, would you prefer to use a service like SendGrid/AWS SES, or make direct SMTP calls?” * “For file storage, would you like to use AWS S3, Google Cloud Storage, or local file system?” * **Present Trade-offs**: Briefly explain the differences (ease of use, cost, features, maintenance) 3. **Identify Needed Components** Carefully review the user’s task and identify all components needed: * **Environment Variables**: List all configuration variables needed (e.g., base url, timeouts, ports, URLs) * **Secrets**: List all sensitive credentials needed (e.g., api keys, passwords, tokens) * **Input Parameters**: Define what parameters the process should accept (e.g., email, dates, types) * **Dependencies**: List all dependencies the task needs (from npm or pypi) * **Modules**: List all modules you think could be created not only for this task, but for future tasks (ie: if you are working with one API, it’s interesting to create a module with one client for that API) 4. **Define YepCode Input Parameter Requirements** (if applicable): * What fields are needed? * What field types (text, select, date, etc.)? * What validations are required? * Any dynamic fields that need API calls before setting them (e.g., enums from external APIs)? 5. **Present the Plan**: Clearly explain to the user what you’re going to build and get explicit approval. You can use a structure like: * **What I’ll build**: Short description of the process/module * **Environment variables**: Configuration vars you’ll create; secrets the user must create (marked clearly) * **Input parameters**: List with types and descriptions * **Dependencies**: Packages and versions (verify they exist and use stable versions when possible) * **Reusable modules**: Which modules you’ll create and why they’re reusable * **Expected behavior**: Main steps and return/outcome * **Ask**: “Shall I proceed?” and wait for Yes/No/Modify Example: “Ok, I’m going to create a process with the following input parameters fields: email, types (it will be a select and we’ll show the current available types), the date from and to. You’d have to define the API\_KEY to be used (and I’ll create BASE\_URL variable). Do you want me to go ahead?” 6. **Wait for User Confirmation**: Do not proceed until the user explicitly confirms the plan. ### Phase 2: Iterative Development [Section titled “Phase 2: Iterative Development”](#phase-2-iterative-development) Work in small, iterative steps with user confirmation at each step: #### Iteration 1: Setup & Discovery [Section titled “Iteration 1: Setup & Discovery”](#iteration-1-setup--discovery) 1. **Create Environment Variables**: * Explain which env vars you’ll create and why * Ask user to manually create sensitive variables * Explain to the user: “I’ve created the configuration variables. Please now create the following sensitive variables: \[list them]. Let me know when you’re done.” * Wait for user confirmation 2. **Discovery Script** (if needed): * Write a simple discovery script to explore the services to be used (APIs, databases…) (e.g., fetch available types, validate authentication) * Explain what the script will do * Get user confirmation * Execute using `run_code` MCP tool to validate connectivity and understand the services * Share results with the user #### Iteration 2+: Incremental Implementation [Section titled “Iteration 2+: Incremental Implementation”](#iteration-2-incremental-implementation) For each subsequent iteration: 1. **Explain Next Step**: Clearly describe what you’re going to implement in this iteration * Example: “Now I’m going to create the main script that will use the process input form parameters, needed variables and dependencies to implement \[user task]. It will \[script explanation].” 2. **Get Confirmation**: Wait for user approval to proceed 3. **Implement**: Write the code following YepCode code guidelines * Follow the language-specific code rules (JavaScript/Python) * Use proper error handling * Add logging for debugging * Include input validation * Use return if the task needs to provide an structured (maybe JSON) result 4. **Validate**: * Use `run_code` MCP tool to test pieces of functionality * Share validation results with user * If errors occur, explain them and propose fixes 5. **Create/Update YepCode Process** (when ready): * Update process code * Configure process input parameters * Set descriptions * Explain what you’ve updated 6. **Review Cycle**: * Inform the user how the process have been updated * Ask user to review the changes * User can make manual changes if desired * If user makes changes, continue from the latest version 7. **Confirm Before Next Iteration**: Ask if the user wants to proceed to the next iteration or if changes are needed ### Phase 3: Testing & Refinement using YepCode CLI [Section titled “Phase 3: Testing & Refinement using YepCode CLI”](#phase-3-testing--refinement-using-yepcode-cli) 1. **Test Execution**: Follow YepCode CLI rules to propose running a complete execution test using YepCode CLI commands 2. **Get User Confirmation**: Wait for approval 3. **Execute**: Use YepCode CLI commands to run the complete process with parameters test data 4. **Review Results**: Analyze output/errors together with user 5. **Iterate if Needed**: If issues found, explain what needs fixing and repeat the cycle 6. **Offer the user next steps**: Inform the user about the YepCode possibilities: * Maybe this process needs to be scheduled, a webhook is needed (maybe with auth), a form is needed, or it should be exposed as an MCP tool (just tag it). Explain how to use them. * Suggest using YepCode CLI to push the process to cloud when it’s ready. ## Creating MCP Tools [Section titled “Creating MCP Tools”](#creating-mcp-tools) When the user asks to create an MCP tool, **do not** write standalone MCP server code or ask the user to wire it up manually. YepCode natively supports exposing processes as MCP tools through the YepCode MCP Server. To create an MCP tool: 1. **Create a YepCode process** that implements the tool’s logic 2. **Define its input parameters** using JSON Schema (`parametersSchema.json`) — these become the tool’s parameters 3. **Tag the process** with the appropriate tag (e.g. `mcp-tool`) so it gets exposed as an MCP tool 4. The process will be **automatically available** as a tool in any MCP client connected to the YepCode MCP Server This means any YepCode process can become an MCP tool with zero extra infrastructure — just tag and go. ## Code Quality Standards [Section titled “Code Quality Standards”](#code-quality-standards) All generated code must include: * **Error Handling**: Try-catch blocks with meaningful error messages * **Logging**: Console logs at key decision points * **Validation**: Input parameter validation at start of process * **Comments**: Explain complex logic, not obvious code * **Modularity**: Extract reusable logic to modules when appropriate * **Resource Cleanup**: Close connections, clear temp files ## Security Guidelines [Section titled “Security Guidelines”](#security-guidelines) * **Never** hardcode secrets (API keys, tokens, passwords). * **Always** use variables/environment variables for sensitive values. * **Never** log secrets (mask or omit). * **Validate** all external inputs before processing. ## Error Handling [Section titled “Error Handling”](#error-handling) 1. **Explain Errors**: When execution fails, clearly explain what went wrong 2. **Propose Solutions**: Suggest what changes are needed to fix the issue 3. **Get Confirmation**: Don’t automatically retry without user awareness 4. **Learn & Adapt**: Use error information to refine the approach 5. **Iterate**: Sometimes failures reveal missing requirements—update the plan accordingly ## Available YepCode MCP Tools [Section titled “Available YepCode MCP Tools”](#available-yepcode-mcp-tools) Use these tools appropriately during the workflow: * `run_code`: Execute JavaScript/Python code for validation and testing * `yc_api_`: Execute YepCode API methods for managing YepCode resources (e.g. `yc_api_create_process`, `yc_api_update_process`, `yc_api_delete_process`, etc.) **Tool Usage Guidelines:** * Use `run_code` for quick validation before updating process files * Use `yc_api_` to execute YepCode API methods for managing YepCode resources (e.g. `yc_api_create_process`, `yc_api_update_process`, `yc_api_delete_process`, etc.) * Use any other YepCode MCP tools if it’s needed or asked by the user to complete the task. ## Communication Guidelines [Section titled “Communication Guidelines”](#communication-guidelines) 1. **Be Transparent**: Always explain what you’re about to do and why 2. **Be Patient**: Wait for user confirmation at each significant step 3. **Be Detailed**: When presenting plans or changes, be specific 4. **Be Helpful**: If user asks for changes, adapt the plan accordingly 5. **Be Proactive with Errors**: If something fails, explain why and propose solutions 6. **Don’t Assume**: If something is unclear, ask the user rather than guessing ## Variables and Environment File Handling [Section titled “Variables and Environment File Handling”](#variables-and-environment-file-handling) When modifying workspace variables (e.g. `variables.env`): * **Never overwrite the entire file** when adding or updating variables. Overwriting removes every variable not included in the new content and can break other processes. * **Always read the file first** to see existing variables. * **Make targeted edits only**: append new variables at the end, or update/remove only the specific lines you intend to change. Prefer appending or updating; remove variables only when the user explicitly asks. * If your environment supports a “search and replace” or “patch” workflow, use that instead of rewriting the whole file. ## Module File Naming [Section titled “Module File Naming”](#module-file-naming) * **Modules MUST use** the format `/.js` (JavaScript) or `/.py` (Python). Example: `modules/shopify-client/shopify-client.js` or `modules/sendgrid-client/sendgrid-client.py`. * **Never use** `index.js` or `main.py` for modules—those entry filenames are only for processes. * **Never** put the module file at the root of `modules/` without a folder; each module must live in its own folder named after the module slug. ## Anti-Patterns to Avoid [Section titled “Anti-Patterns to Avoid”](#anti-patterns-to-avoid) **Don’t**: Make assumptions about API structure without testing **Do**: Use discovery scripts to explore APIs first **Don’t**: Create multiple env vars without checking what exists **Do**: Review existing variables first **Don’t**: Overwrite the entire variables file when adding or updating a variable **Do**: Read the file first, then append or update only the specific variable(s) needed **Don’t**: Write entire complex process without testing parts **Do**: Test critical logic with `run_code` before integrating **Don’t**: Assume implementation approach when alternatives exist **Do**: Present options and ask user to choose (e.g., service vs direct SMTP, different payment providers, storage solutions) **Don’t**: Engage in trial-and-error (trying multiple fixes without clear evidence of the root cause) **Do**: If uncertain or after repeated failures, ask the user for clarification and present alternatives instead of guessing ## When to Ask for Help [Section titled “When to Ask for Help”](#when-to-ask-for-help) Ask the user for clarification instead of guessing when: * **Ambiguous requirements**: Multiple valid interpretations exist * **Missing information**: Required details (credentials, endpoints, package names) are not provided * **Repeated failures**: Tests or runs fail multiple times despite fixes * **Architecture or trade-off decisions**: The user should choose between options * **Security concerns**: Implementation could expose sensitive data * **Uncertain root cause**: You don’t have enough context to confidently fix an error **Template**: “I need clarification before proceeding: \[specific question]. The options are: \[A] or \[B]. Which would you prefer?” ## Important Notes [Section titled “Important Notes”](#important-notes) * **Never make bulk changes without confirmation** * **Always check existing environment variables before asking user to create them** * **Never overwrite the full variables file**—only add or update specific variables so others are not removed * **Break complex tasks into small, manageable iterations** * **Keep the user in the loop at every step** * **Maintain verbose logging in all scripts for debugging** * **Use only user-provided information; avoid assumptions** * **If user makes manual changes in YepCode Cloud, always retrieve the latest version (e.g. `yepcode pull`) before continuing** * **Before adding dependencies**, verify the package exists and consider using a recent stable version (e.g. via npm/pypi or available tooling) * **Before using any yepcode.* API, verify it exists in the official guidelines*\* * **Never assume API patterns from other frameworks apply to YepCode** ## Example Interaction [Section titled “Example Interaction”](#example-interaction) **User**: “Create a process to fetch new orders from Shopify API and send email notifications with order details to customers” **Agent**: “I’ll help you create this integration. First, for sending emails, would you prefer: 1. **Email Service** (SendGrid, AWS SES) - easier setup, better deliverability 2. **Direct SMTP** - more control, no third-party needed Which approach?” **User**: “SendGrid” **Agent**: “Perfect! Here’s the plan: * Input parameters: `dateFrom` (date), `dateTo` (date), `orderStatus` (select) * Variables needed: * `SHOPIFY_API_KEY`, `SHOPIFY_SHOP_URL` (you’ll create) * `SENDGRID_API_KEY` (you’ll create) * `SENDGRID_FROM_EMAIL` (I’ll create with default) * Dependencies: @shopify/shopify-api, @sendgrid/mail * Modules: I’ll create `shopify-client` and `sendgrid-client` for reusability Steps: 1. Test Shopify & SendGrid connectivity with a discovery script 2. Implement order fetching logic 3. Implement email templating and sending 4. Test end-to-end with sample data Shall I proceed?” **User**: “Yes” **Agent**: “I’ve created `SENDGRID_FROM_EMAIL`. Please create these sensitive variables: `SHOPIFY_API_KEY`, `SHOPIFY_SHOP_URL`, `SENDGRID_API_KEY`. Let me know when ready.” **User**: “Done” **Agent**: “Thanks! Now I’ll run a discovery script to test connectivity with both Shopify and SendGrid, and fetch sample order data to understand the structure.” *\[Agent runs discovery script]* **Agent**: “Great! Both connections are working: * Shopify: Successfully connected to your shop, found 3 order statuses available (pending, processing, completed) * SendGrid: API key validated, ready to send emails I can see the order structure includes: order\_id, customer\_email, order\_total, items. Now I’ll create the main process with the order fetching and email sending logic. Should I proceed?” **User**: “Yes” **Agent**: “Process created successfully! I’ve implemented: * Order fetching from Shopify with date range and status filtering * Email template with order details * Error handling and logging The process is ready. Would you like me to run a test execution with sample data?” *\[… continues with iterative development]* # YepCode Command Line Interface Rules > Comprehensive guidelines for AI agents to use YepCode CLI for local development, testing, and synchronization with YepCode Cloud. Comprehensive guidelines for AI agents to use YepCode CLI for local development, testing, and synchronization with YepCode Cloud. [Download this file](/docs/ai-rules/cli.md) ## What is YepCode CLI? [Section titled “What is YepCode CLI?”](#what-is-yepcode-cli) The YepCode CLI facilitates interaction with YepCode Cloud directly from your local workstation’s command line. It’s particularly useful for developing and testing processes locally. ## Command Flow [Section titled “Command Flow”](#command-flow) **When making changes and testing:** 1. Optionally run `yepcode pull` first if the user (or someone else) may have changed resources in YepCode Cloud, so you work with the latest version. 2. Make changes to local files (processes, modules, variables, etc.) 3. Run `yepcode add` **only when you have created NEW resources** (new process, new module, new dependency, or new variable). For updates to existing process or module code, skip this step. 4. Run `yepcode dependencies:install` if you have changed dependencies in the local dependencies folder (dependencies/package.json or dependencies/requirements.txt) 5. Run `yepcode run` to test (execute the process locally for development/testing purposes) 6. Run `yepcode push` to deploy to cloud (when ready for production synchronization). Run after any local changes; run `yepcode add` first if you added new resources in step 3. ## Core CLI Commands [Section titled “Core CLI Commands”](#core-cli-commands) ### `yepcode add` [Section titled “yepcode add”](#yepcode-add) **Purpose**: Register **new** local resources (new process, new module, new dependency, or new variable) with the CLI so they can be executed or deployed. It may fix the error “Local process not found” when you have just created that process. **Usage**: ```sh yepcode add ``` **When to use**: * After creating a **new** process, **new** module, **new** dependency, or **new** variable * Before running `yepcode run` or `yepcode push` when such new resources exist **When not to use**: * After only updating existing process or module code (use `yepcode push` directly) * After only updating existing variables (use `yepcode push` directly) **What it does**: * Registers new resources in the local workspace * Makes new processes/modules/variables/dependencies ready for run or push **Important**: Run `yepcode add` when you have **new** resources; for existing resources, `yepcode push` is enough. ### `yepcode dependencies:install` [Section titled “yepcode dependencies:install”](#yepcode-dependenciesinstall) **Purpose**: Install dependencies in the local workspace. **Usage**: ```sh yepcode dependencies:install ``` **When to use**: * After changing dependencies in the local dependencies folder (dependencies/package.json or dependencies/requirements.txt) **What it does**: * Installs dependencies in the local workspace ### `yepcode run --parameters ` [Section titled “yepcode run \ --parameters \”](#yepcode-run-process-slug---parameters-filepath--stringified-json) **Purpose**: Execute a process locally for development/testing **Usage**: ```sh # Using a parameters file yepcode run --parameters # Using stringified JSON yepcode run --parameters '{"key": "value"}' # Using default parameters.json from process folder yepcode run ``` **When to use**: * To test process execution locally * To debug issues with detailed logs * During iterative development to validate changes **What it does**: * Executes the process code locally * Uses environment variables from `variables.env` and `variables.local.env` * Uses provided parameters or default `parameters.json` * Shows execution logs * Shows execution results and errors (if any) **Prerequisites**: * Run `yepcode add` first if the process (or other resource) was just created ### `yepcode pull` [Section titled “yepcode pull”](#yepcode-pull) **Purpose**: Sync changes from YepCode Cloud to your local workspace. **Usage**: ```sh yepcode pull ``` **When to use**: * Before starting work if others may have changed resources in the cloud * When the user has made changes in YepCode Cloud and you need the latest version locally * When you want to discard local changes and match the cloud state **What it does**: * Downloads the latest processes, modules, variables, and dependencies from the cloud * Updates your local files to match the cloud **Force pull**: If both local and cloud have changes, pull may fail. Use the `--force` flag only when intended, and **always ask for user confirmation** before using force. ### `yepcode push` [Section titled “yepcode push”](#yepcode-push) **Purpose**: Deploy local changes to YepCode cloud **Usage**: ```sh yepcode push ``` **When to use**: * When the process is ready for production * After testing locally with `yepcode run` * To make changes available in the cloud **What it does**: * Uploads local files to YepCode cloud * Updates cloud resources with local changes * Makes the process available for cloud execution **Prerequisites**: * Run `yepcode add` first if you created new resources (new process, module, dependency, or variable) * Recommended to run `yepcode run` first to test **Force push**: If both local and cloud have changes, push may fail. Use the `--force` flag only when the user intends to overwrite cloud with local; **always ask for user confirmation** before using force. ## Complete Workflow Examples [Section titled “Complete Workflow Examples”](#complete-workflow-examples) ### Example 1: Development Cycle [Section titled “Example 1: Development Cycle”](#example-1-development-cycle) **Agent**: “I’ve implemented the script. Would you like to test it locally?” **User**: “Yes” **Agent**: “I’ll sync and run it for you.” *\[Agent runs yepcode add]* *\[Agent runs yepcode dependencies:install]* *\[Agent runs yepcode run]* **Agent**: “The logs look good! Would you like to push to production?” **User**: “Yes” **Agent**: “Deploying to production now.” *\[Agent runs yepcode push (no need to run yepcode add again since nothing changed)]* ### Example 2: Testing a New Process [Section titled “Example 2: Testing a New Process”](#example-2-testing-a-new-process) **User**: “I need to test the new shopify-order-sync process locally with some parameters” **AI**: “I’ll add the process first and then run it for you.” ```sh yepcode add ``` Install dependencies if needed: ```sh yepcode dependencies:install ``` ```sh yepcode run shopify-order-sync --parameters '{"dateFrom": "2024-01-01", "dateTo": "2024-01-31"}' ``` ### Example 3: Deploying to Production [Section titled “Example 3: Deploying to Production”](#example-3-deploying-to-production) **User**: “The inventory-sync process is ready for production. Please deploy it to the cloud.” **AI**: “I’ll sync the process and push it to production.” ```sh yepcode add ``` ```sh yepcode push ``` ## Critical Rules [Section titled “Critical Rules”](#critical-rules) * **Run `yepcode add`** when you have created **new** resources (new process, module, dependency, or variable); then run `yepcode run` or `yepcode push` as needed. * **Run `yepcode push`** after any local changes to sync to cloud; run `yepcode add` first only if new resources were created. * **Run `yepcode pull`** before making changes when the user or others may have updated resources in the cloud. * **NEVER run `yepcode run`** without having run `yepcode add` first when the process (or other resource) was just created. * **Ask for user confirmation** before using `--force` on `yepcode push` or `yepcode pull`. # Plans and Limits > Explore the details about YepCode pricing plans, usage limits, and available features. YepCode offers a variety of [pricing plans](https://yepcode.io/pricing) tailored to your needs. We provide a **GENEROUS FREE TIER** for individual developers to explore the platform at no cost. This is an ideal option for solo developers. For users requiring more executions, extended execution time, or collaborative features within a team, upgrading to a higher plan is available. YepCode is an *enterprise-ready* platform, and we can discuss and provide a personalized **ENTERPRISE** plan for clients with specific needs. ## What are Yeps? [Section titled “What are Yeps?”](#what-are-yeps) In the YepCode universe, a Yep represents one second of execution time for a given [process](/docs/processes). Each time you run a process using any method ([on-demand](/docs/executions/on-demand), [webhook](/docs/executions/webhooks), or [scheduled](/docs/executions/scheduled) / cron jobs), one Yep is consumed for each second this execution takes. Each plan includes a monthly allocation of Yeps, and the consumption counter resets at the end of each month. Paid plans allow you to continue using your account beyond the included Yeps, with additional Yeps billed on a pay-as-you-go basis. Check our [pricing page](https://yepcode.io/pricing) for details on each plan’s Yeps allocation and the price of additional Yeps. ## On-Premise Deployments [Section titled “On-Premise Deployments”](#on-premise-deployments) Visit our [on-premise](/docs/on-premise) docs page to learn more about how YepCode can be used in your system infrastructure. On-premise versions are available on *GROWTH* and *ENTERPRISE* plans: * GROWTH: Only the [executors on-premise](/docs/on-premise/executors) flavor is available. * ENTERPRISE: Executors on-premise or [full stack on-premise](/docs/on-premise/full-stack) options are available. In the following sections, the GROWTH plan limits differ depending on whether YepCode Cloud or executors on-premise installation is used. ## Daily Limits [Section titled “Daily Limits”](#daily-limits) These limits reset every night at 00:00 CET and include two conditions: | Plan | Max Executions per day | Max Yeps per day | | ---------- | ---------------------- | ---------------- | | DEVELOPER | 300 | 1,800 Yeps | | STARTER | - | - | | GROWTH | - | - | | ENTERPRISE | - | - | ## Monthly Limits [Section titled “Monthly Limits”](#monthly-limits) These limits reset every 1st day of the month at 00:00 CET and include the amount of Yeps: | Plan | Max Yeps per month | | ---------- | ------------------ | | DEVELOPER | 50K | | STARTER | 15M | | GROWTH | 150M | | ENTERPRISE | TBD | ## Max Processes [Section titled “Max Processes”](#max-processes) [Processes](/docs/processes) are the core of YepCode, each plan has a limit on the number of processes that can be created. | Plan | Max processes | | ---------- | ------------- | | DEVELOPER | 1,000 | | STARTER | Unlimited | | GROWTH | Unlimited | | ENTERPRISE | Unlimited | ## HTTP Queries Per Second Limits [Section titled “HTTP Queries Per Second Limits”](#http-queries-per-second-limits) Each plan has a limited number of requests per second, affecting both webhooks and YepCode Form submissions. Exceeding the limit results in a 429 HTTP error code (Too Many Requests). | Plan | Max Requests per second | Max Requests per minute | | ---------- | ----------------------- | ----------------------- | | DEVELOPER | 1 | 5 | | STARTER | 10 | Unlimited | | GROWTH | 50 | Unlimited | | ENTERPRISE | Unlimited | Unlimited | ## Max Time per Execution [Section titled “Max Time per Execution”](#max-time-per-execution) Each plan has a maximum execution time. If an execution exceeds this limit, it will be terminated by the system. | Plan | Max time per execution | | ----------------------------- | ---------------------- | | DEVELOPER | 30 seconds | | STARTER | 1 hour | | GROWTH - YepCode Cloud | 12 hours | | GROWTH - Executors on-premise | TBD | | ENTERPRISE | TBD | For clients needing to surpass these limits, a custom *ENTERPRISE* plan can be discussed, allowing for services to run for as long as needed. ## Max Delay in Execution Start [Section titled “Max Delay in Execution Start”](#max-delay-in-execution-start) Performance is crucial for automation workflows, and we’ve designed our infrastructure to provide fast execution start times across all our plans. **Execution start delay** refers to the time from when an execution is created (webhook invocation, scheduled execution or cron job, or on-demand execution) until it begins running. This metric does not include: * Time for installing dependencies (if not cached) * Time spent in team execution queues if [max concurrent executions](#max-concurrent-and-queued-executions) is reached * Actual execution runtime The following table shows the expected start delays (95th and 99th percentiles) per plan: | Plan | 95th percentile start delay | 99th percentile start delay | | ---------- | --------------------------- | --------------------------- | | DEVELOPER | No guarantees (best effort) | No guarantees (best effort) | | STARTER | < 15 seconds | < 30 seconds | | GROWTH | < 3 seconds | < 5 seconds | | ENTERPRISE | < 1 second | < 2 seconds | Note These are target performance metrics. Actual performance may vary based on system load, execution complexity, and other factors. Enterprise customers receive dedicated infrastructure for optimal performance. ## Max Memory Usage [Section titled “Max Memory Usage”](#max-memory-usage) Each plan has a maximum memory allocation limit for process executions. If an execution exceeds this limit, it will be terminated by the system. | Plan | Max memory usage | | ---------- | ---------------- | | DEVELOPER | 150Mb | | STARTER | 300Mb | | GROWTH | 600Mb | | ENTERPRISE | TBD | ## Max Team Members [Section titled “Max Team Members”](#max-team-members) Collaboration is a key feature of YepCode, allowing multiple developers to share a common workspace for processes and executions with an [audit module](/docs/audit-events) for monitoring. *DEVELOPER* plan is designed for solo use, while paid plans support collaboration. | Plan | Max team members | | ---------- | ---------------- | | DEVELOPER | 1 member | | STARTER | 10 members | | GROWTH | Unlimited | | ENTERPRISE | Unlimited | ## Max Concurrent and Queued Executions [Section titled “Max Concurrent and Queued Executions”](#max-concurrent-and-queued-executions) The platform limits the number of concurrent executions a team may run at the same time. We also allow to queue executions when this limit is reached, and process them one by one as soon as a previous execution finishes. For example, in the STARTER plan, if you send 50 executions at the same time, ten will be executed concurrently, and the rest will be queued. As soon as a previous execution finishes, the next one in the queue will be executed. | Plan | Max concurrent executions | Max queued executions | | ----------------------------- | ------------------------- | --------------------- | | DEVELOPER | 1 | - | | STARTER | 10 | 100 | | GROWTH - YepCode Cloud | 50 | 1,000 | | GROWTH - Executors on-premise | TBD | TBD | | ENTERPRISE | TBD | TBD | ## Executions History [Section titled “Executions History”](#executions-history) The execution logs and results are available for a certain amount of time, and after that, they are removed. | Plan | Executions history | | ---------- | ------------------ | | DEVELOPER | 3 days | | STARTER | 7 days | | GROWTH | 30 days | | ENTERPRISE | TBD | ## YepCode Forms [Section titled “YepCode Forms”](#yepcode-forms) YepCode Forms allow you to enable forms for your processes. The number of forms is limited based on your plan. Forms in DEVELOPER and STARTER plans include a YepCode branding asset that shouldn’t be hidden in webpages where the form is embedded. | Plan | Allowed YepCode Forms | YepCode Branding | | ---------- | --------------------- | -------------------------------------------------------------------- | | DEVELOPER | 1 | ![Powered by YepCode](https://yepcode.io/sdk/powered-by-yepcode.svg) | | STARTER | 10 | - | | GROWTH | Unlimited | - | | ENTERPRISE | Unlimited | - | ## YepCode Landings [Section titled “YepCode Landings”](#yepcode-landings) YepCode Landings allows to manage countless variations of landing pages effortlessly. The number of landing pages is limited based on your plan. | Plan | Allowed YepCode Landing Pages | | ---------- | ----------------------------- | | DEVELOPER | - | | STARTER | 10 | | GROWTH | 1,000 | | ENTERPRISE | Unlimited | ## Execution Input Parameters Max Size [Section titled “Execution Input Parameters Max Size”](#execution-input-parameters-max-size) Each execution may have its own [input parameters](/docs/processes/input-params) object. This payload has size limits, and if exceeded, the execution will be discarded, returning a 413 HTTP error code (Content Too Large). Two types of limits exist: the maximum payload size for all plain text parameters and the max payload size for all files parameters (each file is available through a URL at execution time). | Plan | Max size for text parameters | Max size for files | | ---------- | ---------------------------- | ------------------ | | DEVELOPER | 50Kb | - | | STARTER | 100Kb | 1Mb | | GROWTH | 500Kb | 15Mb | | ENTERPRISE | TBD | TBD | ## Execution Result Max Size [Section titled “Execution Result Max Size”](#execution-result-max-size) Each execution may have its own result object, which is stored and returned to webhook invocations. | Plan | Max result size | | ---------- | --------------- | | DEVELOPER | 50Kb | | STARTER | 100Kb | | GROWTH | 500Kb | | ENTERPRISE | TBD | ## Executions Log Max Lines & Size [Section titled “Executions Log Max Lines & Size”](#executions-log-max-lines--size) Each execution has its own log, available during the execution history period. The log has a max size and a max number of lines. If the process execution output exceeds these limits, no more log entries will be saved. | Plan | Executions log max size | Executions log max lines | | ---------- | ----------------------- | ------------------------ | | DEVELOPER | 100Kb | 100 | | STARTER | 250Kb | 250 | | GROWTH | 500Kb | 500 | | ENTERPRISE | TBD | TBD | ## Package Dependencies [Section titled “Package Dependencies”](#package-dependencies) YepCode allows you to choose and use any external package from `npm` or `pypi` repositories. The number of package dependencies is limited based on your plan. We also limit the number of dependency sets that can be installed by day. | Plan | Max dependencies | Max installations by day | | ---------- | ---------------- | ------------------------ | | DEVELOPER | 10 | 10 | | STARTER | 25 | 100 | | GROWTH | Unlimited | Unlimited | | ENTERPRISE | Unlimited | Unlimited | Furthermore, YepCode allows to define the packages at team or process level, so you can use different packages for different processes. But this process level dependency definition is limited to GROWTH and ENTERPRISE plans. ## File system limits [Section titled “File system limits”](#file-system-limits) YepCode allows to store files in the file system used during the execution of a process. The number and size of files is limited based on your plan. | Plan | Max files | Local disk size | | ---------- | --------- | --------------- | | DEVELOPER | Unlimited | 5Mb | | STARTER | Unlimited | 250Mb | | GROWTH | Unlimited | 5Gb | | ENTERPRISE | Unlimited | Unlimited | ## Storage limits [Section titled “Storage limits”](#storage-limits) YepCode allows to store files in the cloud storage. The number and size of files is limited based on your plan. | Plan | Max files | Max file size | | ---------- | --------- | ------------- | | DEVELOPER | 5 | 5Mb | | STARTER | 100 | 25Mb | | GROWTH | 1,000 | 50Mb | | ENTERPRISE | Unlimited | Unlimited | ## Audit Events History [Section titled “Audit Events History”](#audit-events-history) The audit module keeps track of everything happening in the team, including executions, code changes, and webhook invocations. | Plan | Audit events history | | ---------- | -------------------- | | DEVELOPER | - | | STARTER | - | | GROWTH | 3 months | | ENTERPRISE | TBD | ## Datastore [Section titled “Datastore”](#datastore) Visit our [datastore](/docs/datastore) docs to understand how to use this simple, fast, and powerful key-value storage system. The Datastore is available on paid plans with specific limits: | Plan | Max entries | Max entry size | | ----------------------------- | ----------- | -------------- | | DEVELOPER | - | - | | STARTER | 1,000 | 5Kb | | GROWTH - YepCode Cloud | 20,000 | 50Kb | | GROWTH - Executors on-premise | TBD | TBD | | ENTERPRISE | TBD | TBD | ## Identity Brokering [Section titled “Identity Brokering”](#identity-brokering) For companies wanting to use an external identity provider, YepCode offers integration with [OpenID](https://en.wikipedia.org/wiki/OpenID) or [SAML](https://en.wikipedia.org/wiki/Security_Assertion_Markup_Language) protocols. These integrations are available on *GROWTH* or *ENTERPRISE* plans. ## Users Federation [Section titled “Users Federation”](#users-federation) Another authentication option is users federation with LDAP or Active Directory, available exclusively on *ENTERPRISE* plans. # Deprecated Credentials Migration Guide > Learn how to migrate your YepCode deprecated credentials using dependencies and environment variables. ## Why are credentials being deprecated? [Section titled “Why are credentials being deprecated?”](#why-are-credentials-being-deprecated) Since we added the ability to use dependencies in YepCode, it has created a maintainability challenge supporting all package versions with Credentials. As a result, we are deprecating them. You can still securely initialize your clients using environment variables. ## How to migrate [Section titled “How to migrate”](#how-to-migrate) We’ll use [dependencies](/docs/dependencies/) and [team variables](/docs/processes/team-variables/) to migrate your current credentials. Lets see a real example: * JavaScript For this example we’ll use the [nodemailer](https://www.npmjs.com/package/nodemailer) credential integration (other credentials will follow the same approach). Your current process code should look like this: ```js const mailClient = yepcode.integration.nodemailer("nodemailer-credentials"); await mailClient.sendMail({ from: "YepCode 🤖 ", to: "support@yepcode.io", subject: "YepCode nodemailer credential", text: "This is a message from YepCode using nodemailer credential", }); console.log("Email sent"); ``` ### 1. Import the required dependency package (JavaScript) [Section titled “1. Import the required dependency package (JavaScript)”](#1-import-the-required-dependency-package-javascript) ```diff +const nodemailer = require("nodemailer"); const mailClient = yepcode.integration.nodemailer("nodemailer-credentials"); await mailClient.sendMail({ from: "YepCode 🤖 ", to: "support@yepcode.io", subject: "YepCode nodemailer credential", text: "This is a message from YepCode using nodemailer credential", }); console.log("Email sent"); ``` ### 2. Initialize the client (JavaScript) [Section titled “2. Initialize the client (JavaScript)”](#2-initialize-the-client-javascript) Follow the package docs to know how to initialize the client instead of using the credential integration, in this case we are using the [`createTransport` method](https://nodemailer.com/usage#create-a-transporter) from [nodemailer usage section](https://nodemailer.com/usage). Note You may look our [Recipes Platform](/recipes/) to find examples of how to use dependencies in your processes. ```diff const nodemailer = require("nodemailer"); -const mailClient = yepcode.integration.nodemailer("nodemailer-credentials"); +const mailClient = nodemailer.createTransport({ host: process.env.nodemailerHost, port: 587, secure: false, // If SSL is required, you'd need to set secure: true connectionTimeout: 5000, auth: { user: process.env.nodemailerUser, pass: process.env.nodemailerPass, }, }); await mailClient.sendMail({ from: "YepCode 🤖 ", to: "support@yepcode.io", subject: "YepCode nodemailer credential", text: "This is a message from YepCode using nodemailer credential", }); console.log("Email sent"); ``` ### 3. Save the process (JavaScript) [Section titled “3. Save the process (JavaScript)”](#3-save-the-process-javascript) Hit the `Save` button in your process status bar (bottom right) to update it. ![Save process](/docs/img/screenshots//credentials-migration-guide/js/save-button.png) ### 4. Install the missing dependencies (JavaScript) [Section titled “4. Install the missing dependencies (JavaScript)”](#4-install-the-missing-dependencies-javascript) After saving the process you’ll see some alerts in the process editor related to missing dependencies and variables: ![Alerts](/docs/img/screenshots//credentials-migration-guide/js/alerts.png) We’ll need to add them before executing the process. #### 4.1 Add missing dependencies (JavaScript) [Section titled “4.1 Add missing dependencies (JavaScript)”](#41-add-missing-dependencies-javascript) YepCode will automatically detect missing dependencies for your source code. You can see the missing dependencies by clicking the `Dependencies` button in the process status bar: ![Missing dependencies](/docs/img/screenshots//credentials-migration-guide/js/missing-dependencies.png) Add the missing dependencies by clicking the `Add all` button. ![Add all dependencies](/docs/img/screenshots//credentials-migration-guide/js/add-all-dependencies.png) Install the missing dependencies by clicking the `Install` button on the pop up notification. ![Install dependencies](/docs/img/screenshots//credentials-migration-guide/js/dependencies-install.png) #### 4.2 Add missing variables (JavaScript) [Section titled “4.2 Add missing variables (JavaScript)”](#42-add-missing-variables-javascript) YepCode will automatically detect missing variables for your source code. You can see the missing variables in your process right sidebar: ![Missing variables](/docs/img/screenshots//credentials-migration-guide/js/missing-variables.png) Add the missing variables by clicking on each one of them and filling the required information: ![Add variables](/docs/img/screenshots//credentials-migration-guide/js/add-variables.png) Note Remember to secure sensitive variables. ![Add secure variables](/docs/img/screenshots//credentials-migration-guide/js/add-secure-variables.png) * Python For this example we’ll use the [http requests](https://pypi.org/project/requests/) credential integration (other credentials will follow the same approach). Your current process code should look like this: ```py http = yepcode.integration.http("http-credential") try: response = http.get("https://yepcode.io") print(response.text) except Exception as e: print(f"Error sending request: {e}") ``` ### 1. Import the required dependency package (Python) [Section titled “1. Import the required dependency package (Python)”](#1-import-the-required-dependency-package-python) ```diff +import requests http = yepcode.integration.http("http-credential") try: response = http.get("https://api.github.com/user") print(response.json()) except Exception as e: print(f"Error sending request: {e}") ``` ### 2. Initialize the client (Python) [Section titled “2. Initialize the client (Python)”](#2-initialize-the-client-python) Follow the package docs to know how to initialize/use the package instead of using the credential integration, in this case we are using the [`get` method](https://requests.readthedocs.io/en/latest/user/quickstart/#make-a-request) from the requests package. Note You may look our [Recipes Platform](/recipes/) to find examples of how to use dependencies in your processes. ```diff import requests +import os -http = yepcode.integration.http("http-credential") try: headers = { "Authorization": f"Bearer {os.getenv('GITHUB_TOKEN')}", "Accept": "application/vnd.github.v3+json" } response = requests.get("https://api.github.com/user", headers=headers) print(response.json()) except Exception as e: print(f"Error sending request: {e}") ``` ### 3. Save the process (Python) [Section titled “3. Save the process (Python)”](#3-save-the-process-python) Hit the `Save` button in your process status bar (bottom right) to update it. ![Save process](/docs/img/screenshots//credentials-migration-guide/py/save-button.png) ### 4. Install the missing dependencies (Python) [Section titled “4. Install the missing dependencies (Python)”](#4-install-the-missing-dependencies-python) After saving the process you’ll see some alerts in the process editor related to missing dependencies and variables: ![Alerts](/docs/img/screenshots//credentials-migration-guide/py/alerts.png) We’ll need to add them before executing the process. #### 4.1 Add missing dependencies (Python) [Section titled “4.1 Add missing dependencies (Python)”](#41-add-missing-dependencies-python) YepCode will automatically detect missing dependencies for your source code. You can see the missing dependencies by clicking the `Dependencies` button in the process status bar: ![Missing dependencies](/docs/img/screenshots//credentials-migration-guide/py/missing-dependencies.png) Add the missing dependencies by clicking the `Add all` button. ![Add all dependencies](/docs/img/screenshots//credentials-migration-guide/py/add-all-dependencies.png) Install the missing dependencies by clicking the `Install` button on the pop up notification. ![Install dependencies](/docs/img/screenshots//credentials-migration-guide/py/dependencies-install.png) #### 4.2 Add missing variables (Python) [Section titled “4.2 Add missing variables (Python)”](#42-add-missing-variables-python) YepCode will automatically detect missing variables for your source code. You can see the missing variables in your process right sidebar: ![Missing variables](/docs/img/screenshots//credentials-migration-guide/py/missing-variables.png) Add the missing variables by clicking on each one of them and filling the required information. Note Remember to secure sensitive variables. ![Add secure variables](/docs/img/screenshots//credentials-migration-guide/py/add-secure-variables.png) ## Execute your process [Section titled “Execute your process”](#execute-your-process) You can now [execute](/docs/executions) your process as usual 🎉. # Migrating from YepCode Cloud > Run your YepCode workspace on your own infrastructure using the YepCode CLI. This guide walks you through running the same workspace you have on YepCode Cloud on your own infrastructure using the [YepCode CLI](/docs/cli). The migration relies on three CLI capabilities you already have access to: * `yepcode clone` downloads your full team workspace (source code, modules, dependencies, variables and datastore) to a local folder you can version with `git`. * `yepcode run` executes any process locally, exactly as it would in the cloud. * `yepcode http` starts a local HTTP server that mirrors the cloud webhook environment and also serves the form schema and submission endpoints, with the same authentication and signature contract. ## Step 1 — Install the CLI and clone your workspace [Section titled “Step 1 — Install the CLI and clone your workspace”](#step-1--install-the-cli-and-clone-your-workspace) Install the CLI globally: ```sh npm install -g @yepcode/cli ``` Log in and clone your team workspace: ```sh yepcode login yepcode clone ``` The clone produces a folder containing `processes/`, `modules/`, `dependencies/`, `variables.env`, `variables.local.env` and `datastore.json`. See the full layout in [Clone your team workspace locally](/docs/cli#clone-your-team-workspace-locally). We recommend committing the cloned folder to a private git repository so you can track changes and roll back if needed. ## Step 2 — Configure variables and credentials locally [Section titled “Step 2 — Configure variables and credentials locally”](#step-2--configure-variables-and-credentials-locally) `variables.env` lists every team variable name with empty values; `variables.local.env` overrides those and is git-ignored by default. Fill `variables.local.env` with the secrets your processes need (database URLs, API keys, etc.). See [Team variables](/docs/processes/team-variables) for the variable model. If you were still relying on the deprecated built-in credentials, follow the [Deprecated credentials migration guide](/docs/credentials-migration-guide) — the same pattern (dependency package + environment variable) works identically when running locally. ## Step 3 — Install dependencies [Section titled “Step 3 — Install dependencies”](#step-3--install-dependencies) Install both Python and JavaScript dependencies declared in your workspace: ```sh yepcode dependencies ``` See [Manage package dependencies](/docs/cli#manage-package-dependencies) for the available flags. ## Step 4 — Run a process locally [Section titled “Step 4 — Run a process locally”](#step-4--run-a-process-locally) Execute any process by its slug: ```sh yepcode run ``` By default the input is read from `parameters.json` inside the process folder. Pass `--parameters path/to/parameters.json` to override it. See [Execute processes locally](/docs/cli#execute-processes-locally). ## Step 5 — Replace cloud webhooks with `yepcode http` [Section titled “Step 5 — Replace cloud webhooks with yepcode http”](#step-5--replace-cloud-webhooks-with-yepcode-http) Start the local HTTP server that replaces the cloud webhook backend: ```sh yepcode http --port 8080 --auth-user admin --auth-password secret ``` The local server replicates the cloud webhook contract one-to-one: * Same URL shape: `/api//webhooks/`. * Same `yepcode.context.request` (`headers`, `rawBody` / `raw_body`, `query`, `method`). * Same signature verification headers (e.g. `X-Signature-SHA256`, `YepCode-Signature`) — process code that validates signatures keeps working unchanged. See [Webhook executions](/docs/executions/webhooks). Available flags: | Flag | Default | Description | | ----------------- | ------- | ---------------------------------------------------------------------- | | `-P, --port` | `3000` | Port to listen on | | `-l, --logLevel` | `DEBUG` | Log level for process executions (`DEBUG`, `INFO`, `WARNING`, `ERROR`) | | `--auth-user` | — | Basic auth username | | `--auth-password` | — | Basic auth password | | `-j, --jsonLogs` | — | Output process logs as NDJSON | To complete the migration, deploy the cloned workspace and `yepcode http` on a server reachable from your callers, then update upstream integrations from `https://cloud.yepcode.io/api/...` to `https://your-host/api/...`. ## Step 6 — Repoint your forms [Section titled “Step 6 — Repoint your forms”](#step-6--repoint-your-forms) The same `yepcode http` server exposes the form schema and submission endpoints with the same contract used by YepCode Cloud. The only HTML change required is adding the `data-yepcode-form-host-url` attribute pointing at your server: ```diff
``` The same override is supported by the `YepCode.initForm(...)` JS API and the `@yepcode/react-forms` component. See [Override the API host](/docs/forms/customization#override-the-api-host) for all three variants. ## Step 7 — Scheduled executions [Section titled “Step 7 — Scheduled executions”](#step-7--scheduled-executions) The CLI does not include a built-in scheduler. To replace YepCode’s scheduled executions, use a host-level cron entry that calls `yepcode run` (or `curl` against `yepcode http`) on the desired cadence. Example `crontab -e` entry running `my-process` every 15 minutes: ```sh */15 * * * * cd /srv/yepcode/ && /usr/local/bin/yepcode run my-process >> /var/log/yepcode/my-process.log 2>&1 ``` On systems without `cron` you can use the equivalent (`systemd` timers, Windows Task Scheduler, a CI runner with a scheduled workflow, etc.). ## Limitations [Section titled “Limitations”](#limitations) * **Datastore.** `yepcode clone` snapshots your datastore as a single `datastore.json` file, and local executions read and write that file directly. Concurrency and durability guarantees are whatever your local filesystem provides — there is no transactional store backing it. If your processes rely heavily on the datastore, plan to migrate those keys to an external store (Redis, Postgres, etc.) and switch the relevant code paths. * **Audit events, execution history and dashboards.** These are not provided by the CLI. If you need them, add your own logging around `yepcode run` and `yepcode http` (process logs, NDJSON output via `--jsonLogs`, reverse-proxy access logs). These are all the blog entries for YepCode # Yep Agent: The Making Of (how we built a coding agent for YepCode processes) > A behind-the-scenes look at how we built Yep Agent: from early prompt-only prototypes to a secure, containerized OpenCode workflow that creates YepCode processes from natural language—fast, safe, and production-ready. ## Yep Agent, the making of Yep Agent is our newest “build it for me” experience inside YepCode: you describe what you want, and it generates **real, runnable YepCode processes** (JavaScript or Python) as you iterate together. If you like the term *vibe coding*, this is the same idea applied to automation: **Vibe Automation**—but with the guardrails required for production. *** ## The origin story: Rules that let coding agents get the most out of YepCode steroids When coding agents started to get good, we did what every platform team does: we wrote the [rules](/docs/ai-rules/): * Processes are JavaScript/Python scripts, but with **input parameters** defined via JSON Schema and consumed by the code. * You can create and import **modules** to reuse logic across processes. * You have a **datastore** for persistence or **storage** for files. * You can use **environment variables and secrets** safely (and teams need those patterns to be consistent). * Other platform conventions: logs, outputs, execution context, HTTP request/response patterns, and the things that make code *operational*. Because this workflow is “just code”, it worked well from day one: users could pull their workspace with the YepCode CLI, iterate in their favorite IDE (for example [Cursor](https://www.cursor.com/) or [Claude](https://claude.ai/)), and push changes back when ready. In other words: strong results, minimal lock‑in. ### What wasn’t great about the early experience The “use your own agent” workflow had real friction: * You had to work on your **local machine**. * You had to install and configure the [YepCode CLI](/docs/cli/), clone repos, run the agent, and push changes. * The path from “I want this automation” to “it’s running in the cloud” was **not straightforward** for the average user—and even for power users it was slower than it needed to be. So we made a product decision: **the agent must live in the platform**. *** ## Prototype phase: we tried building the agent from scratch Our first serious attempt was to assemble the agent using [Mastra.ai](https://mastra.ai/), a framework that’s great at: * Agentic **workflows** * **Sub-agents** (specialized roles) * Tooling via **MCP** * Modular extensibility The initial strategy was the classic one: a carefully designed workflow where each step is guided by **very detailed prompts**. It got us moving fast—until it didn’t. ### Why prompt-only orchestration hit a wall Two issues appeared quickly: * **Prompt gravity**: prompts became long, fragile, and hard to maintain. Every new edge case added more instructions; every new instruction increased the chance of conflicts. * **Repo exploration wasn’t “real”**: the agent needed better ways to explore a customer codebase—partial searches, contextual queries, quick iteration loops—without us manually feeding it slices of files. * **One-shot code generation**: we needed the agent to generate complete processes/modules (not fragments), and that didn’t work reliably with a prompt-only approach. At that point, we reframed the problem: > We didn’t need “more prompt.” We needed a **coding environment** the agent could actually operate in. *** ## The turning point: integrating OpenCode (running in sandboxes) We landed on a system like [OpenCode](https://opencode.ai/) because it gives you what a serious coding agent needs: * It can run as a **CLI** and as a **server**. * It supports strong tooling: **file search**, edits, running scripts, and extension points (including MCP-style tools). * It naturally enables **modular, distributed workflows** in JavaScript/Python instead of trying to squeeze everything into one mega-prompt. ![Screenshot](/docs/img/screenshots/yep-agent-implementation-plan.png) But integrating that into a multi-tenant platform comes with a non-negotiable requirement: ### The agent must be safe by design If an agent can run commands, read files, and modify code, it must operate in a sandbox that is: * Isolated * Ephemeral when needed * Controllable and observable We already had a battle-tested solution for that: **microVM containers based on [Firecracker](https://firecracker-microvm.github.io/)**, the same approach we use to execute YepCode processes securely. So we did the obvious thing: run the agent runtime in the same security model as everything else. ### How the agent integrates with the platform #### Workspace sync (OpenCode ↔ YepCode) via YepCode CLI OpenCode runs inside a sandboxed container, but the source of truth is still your **remote YepCode workspace repository**. To keep that loop tight and reliable, we use the **YepCode CLI** for synchronization: * **Clone/pull**: when a sandbox starts (or when you resume work), the CLI pulls the latest state of your workspace into the container. * **Local edits**: OpenCode applies changes directly on that working copy (processes, modules, schemas, docs—everything is just code). * **Push back**: once the agent finishes (or you’re happy with the diff), the CLI pushes changes back to the remote YepCode workspace so they can be reviewed, evaluated, and executed in the cloud. ![Screenshot](/docs/img/screenshots/yep-agent-changing-code.png) This keeps the agent workflow aligned with the same Git-based lifecycle teams already use, while avoiding any fragile “state mirroring” mechanisms. #### MCP server integration We also integrated our **MCP server** (built on the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/)) so OpenCode can call YepCode capabilities as tools—**with explicit permissions scoped to the user workspace**. This enables the agent to go beyond “editing files” and actually *operate* the platform, for example: * **Start executions** of the processes it just generated (to validate behavior quickly). * **Create or update schedule configurations** (cron jobs) so automations can run on a cron or time-based setup. * Use the `run_code` tool when it needs to execute small snippets safely as part of a workflow (e.g., validate assumptions, transform data, generate artifacts). ![Screenshot](/docs/img/screenshots/yep-agent-remote-execution.png) The result is a tighter loop: prompt → code → run → iterate—without leaving the platform, and without giving the agent uncontrolled access outside the workspace boundary. ### The importance of `run_code` tool in this process The [`run_code` tool](https://yepcode.io/run) tool is a key piece of Yep Agent. It lets the agent execute small snippets safely as part of a workflow—and more importantly, lets it use your workspace **secrets and environment variables without ever exposing their values to the LLM**. With that approach, the agent can validate assumptions against real services (databases, APIs, third-party tools) using credentials already configured in the workspace, and then use the returned information to keep improving the generated code. *** ## How Yep Agent works (end-to-end) At a high level, Yep Agent is a controlled bridge between: * your prompts * your codebase * a secure execution/workflow environment * and the YepCode primitives that make automations production-ready Here’s the flow: 1. **Spin up an OpenCode instance** If the user doesn’t have an active sandbox, we start one in an isolated container (microVM-based). 2. **Clone the customer workspace via YepCode CLI** The agent works against a real repo checkout—no “paste your code here” workflows. 3. **Process the user prompt** The instruction is forwarded to OpenCode, which plans and executes the work. 4. **Use sub-agents + tools** OpenCode distributes tasks and calls internal tools (search, edits, scripts) and platform-provided tools (secrets access patterns, external integrations via MCP, etc.). 5. **Produce a real result** Changes are applied locally and can then be pushed to the remote YepCode repository for review, evaluation, and execution in the cloud. *** ## What we gained (and why it matters) ### Better UX: no local setup required The biggest win is boring—in the best way: * no local agents to configure * no licenses to manage * no “clone this, install that, run this script, hope it works” Just: prompt → generate → iterate → commit. ### Better engineering: real repo semantics and real tooling Once the agent can do true codebase work (search, contextual reads, incremental diffs), you unlock: * faster iterations * fewer hallucinations * more consistent conventions * easier adoption in existing repositories ### Better governance: security + control plane alignment By running the agent inside isolated containers and aligning it with YepCode’s execution model, we can treat agentic generation like any other operational workflow: * controllable runtime * clearer boundaries * a safer story for teams that care about compliance and risk *** ## Lessons learned (the honest part) * **Prompts are not architecture**. They help, but they don’t replace tooling. * **Agents need real affordances**: search, diffs, execution, iteration loops. * **Security can’t be bolted on**. If an agent can run code, isolation must be foundational. * **“Generated code” only matters if it’s shippable**: it must compile, run, handle inputs, and integrate with the platform primitives teams rely on. *** ## What’s next Yep Agent is the start of a bigger direction: bringing “from idea to production automation” into a single loop inside YepCode. Some areas we’re excited about (and actively exploring): * smarter templates and scaffolds for common automation patterns * better multi-step workflows (plan → implement → validate → iterate) * deeper integrations via MCP-style tools * even more visibility into what the agent did and why *** ## Try it, break it, tell us what you think We’d love your feedback—especially from teams using YepCode to ship real automations under real constraints. * Curious about building a similar agent for your team or product? We can help—[reach out to us](/contact) and tell us what you want to automate. # Validate Stripe Webhook Signatures using request raw body > A comprehensive guide on implementing secure Stripe webhook signature verification with timestamp validation in YepCode using the webhook request raw body feature. When handling Stripe webhooks, it’s crucial to verify that the requests actually come from Stripe. This prevents malicious actors from sending fake payment notifications to your system. Stripe uses HMAC-SHA256 signatures to ensure webhook authenticity, and YepCode’s raw body access makes verification straightforward and secure. ## Setup 1. **Create a webhook endpoint** in your [Stripe Dashboard](https://dashboard.stripe.com/webhooks) pointing to your [YepCode webhook](/docs/executions/webhooks): ```txt https://cloud.yepcode.io/api//webhooks/ ``` 2. **Copy the webhook signing secret** from Stripe (starts with `whsec_`) 3. **Store the secret securely** in YepCode [team variables](/docs/processes/team-variables) as `STRIPE_WEBHOOK_SECRET` or any other name you prefer. ## Signature Verification Implementation * JavaScript ```js const crypto = require("crypto"); const { context: { request }, } = yepcode; const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET; // Get the Stripe signature from headers const stripeSignature = request.headers["stripe-signature"]; if (!stripeSignature) { return { status: 400, body: { error: "Missing Stripe signature header" }, }; } // Verify the webhook signature try { // Parse the signature header (format: t=timestamp,v1=signature) const signatures = stripeSignature.split(",").reduce((acc, pair) => { const [key, value] = pair.split("="); acc[key] = value; return acc; }, {}); const timestamp = signatures.t; const receivedSignature = signatures.v1; if (!timestamp || !receivedSignature) { console.error("Missing timestamp or signature in Stripe header"); return { status: 401, body: { error: "Invalid signature format" }, }; } // Check timestamp to prevent replay attacks (allow up to 5 minutes) const currentTime = Math.floor(Date.now() / 1000); const webhookTime = parseInt(timestamp); const tolerance = 300; // 5 minutes in seconds if (Math.abs(currentTime - webhookTime) > tolerance) { console.error("Webhook timestamp too old, possible replay attack"); return { status: 401, body: { error: "Request timestamp too old" }, }; } // Create the signed payload (timestamp + raw body) const signedPayload = timestamp + "." + request.rawBody; const expectedSignature = crypto .createHmac("sha256", webhookSecret) .update(signedPayload) .digest("hex"); if (receivedSignature !== expectedSignature) { console.error("Stripe webhook signature verification failed"); return { status: 401, body: { error: "Invalid signature" }, }; } console.log("✅ Stripe webhook signature verified successfully"); // Parse the webhook payload const event = JSON.parse(request.rawBody); console.log(`Processing event: ${event.type}`); // Your business logic here return { status: 200, body: { received: true }, }; } catch (error) { console.error("Error processing Stripe webhook:", error); return { status: 500, body: { error: "Internal server error" }, }; } ``` * Python ```python import hmac import hashlib import json import os def main(): request = yepcode.context.request webhook_secret = os.getenv("STRIPE_WEBHOOK_SECRET") # Get the Stripe signature from headers stripe_signature = request.get("headers", {}).get("stripe-signature", "") if not stripe_signature: return {"status": 400, "body": {"error": "Missing Stripe signature header"}} # Verify the webhook signature try: # Parse the signature header (format: t=timestamp,v1=signature) signatures = {} for pair in stripe_signature.split(","): key, value = pair.split("=", 1) signatures[key] = value timestamp = signatures.get("t", "") received_signature = signatures.get("v1", "") if not timestamp or not received_signature: print("Missing timestamp or signature in Stripe header") return {"status": 401, "body": {"error": "Invalid signature format"}} # Check timestamp to prevent replay attacks (allow up to 5 minutes) import time current_time = int(time.time()) webhook_time = int(timestamp) tolerance = 300 # 5 minutes in seconds if abs(current_time - webhook_time) > tolerance: print("Webhook timestamp too old, possible replay attack") return {"status": 401, "body": {"error": "Request timestamp too old"}} # Create the signed payload (timestamp + raw body) raw_body = request.get("raw_body", "") signed_payload = timestamp + "." + raw_body expected_signature = hmac.new( webhook_secret.encode(), signed_payload.encode("utf-8"), hashlib.sha256, ).hexdigest() if received_signature != expected_signature: print("Stripe webhook signature verification failed") return {"status": 401, "body": {"error": "Invalid signature"}} print("✅ Stripe webhook signature verified successfully") # Parse the webhook payload event = json.loads(request.get("raw_body", "")) print(f"Processing event: {event.get('type', '')}") # Your business logic here return {"status": 200, "body": {"received": True}} except Exception as error: print(f"Error processing Stripe webhook: {error}") return {"status": 500, "body": {"error": "Internal server error"}} ``` ## Testing Your Webhook Use the [Stripe CLI](https://stripe.com/docs/stripe-cli) to test your webhook: 1. Log in to Stripe ```sh stripe login ``` 2. Forward events to your YepCode webhook. This will listen for stripe events in your current terminal. ```sh stripe listen --forward-to https://cloud.yepcode.io/api//webhooks/ ``` 3. Copy `stripe listen` output signing secret to your YepCode team variable `STRIPE_WEBHOOK_SECRET`. 4. Open a new terminal and trigger a test event ```sh stripe trigger payment_intent.succeeded ``` 5. Check your YepCode [execution](/docs/executions#execution-detail) logs to see the signature verified and event received. ## Key Points * ✅ Use `request raw body` for signature verification * ✅ Include timestamp validation to prevent replay attacks * ✅ Store webhook secrets in YepCode team variables * ✅ Return proper HTTP status codes (200, 401, 500) * ✅ Handle exceptions gracefully The raw body signature verification ensures that webhooks actually come from Stripe, providing a secure foundation for your payment processing workflows. ## Learn More * [YepCode webhook documentation](/docs/executions/webhooks) * [Stripe webhook security guide](https://stripe.com/docs/webhooks/signatures) # Secure Code Execution in AI Agents: Why Isolation Matters and How YepCode Helps > LLM agents that execute code unlock power—and risk. This post explains why isolation is non‑negotiable and how to execute safely with YepCode Run plus file I/O via YepCode Storage. ## The problem: agents that run code… on your machine Modern agent frameworks let LLMs generate and run code autonomously. That’s powerful—and risky. If code runs directly on the host, a single prompt‑injection or supply‑chain attack can exfiltrate data, delete files, mine crypto, or pivot across your network. A recent survey of secure execution patterns in agents highlights the same conclusion many of us have reached: the only safe way to run LLM‑generated code is to isolate it from your local environment (via sandboxing/containers) and apply strict runtime controls. ## What “secure by design” looks like When you let an LLM execute code, treat it as untrusted by default. A practical baseline includes: * **Isolation**: per‑run sandbox or container, ephemeral filesystem, no host mounts * **Resource limits**: CPU, memory, pids, timeouts, process count * **Egress controls**: restrict outbound network or allowlist domains * **Dependency hygiene**: deterministic installs, separate from host * **Observability**: full logs, return values, and error traces for audit > Market landscape: secure execution for agent code Several companies are actively solving this secure‑execution pattern: * **e2b**: provides hosted sandboxes that execute code out of process with real‑world tools and isolation. See their product overview at [e2b.dev](https://e2b.dev/). * **Daytona**: focuses on standardized, ephemeral cloud development environments that can help teams isolate execution surfaces. Learn more at [daytona.io](https://www.daytona.io/). Many of these approaches give agents a full ephemeral machine/“virtual computer.” That’s powerful, but it can add integration overhead and expand the governance surface. YepCode takes a different path: a **developer‑first** execution plane. Instead of provisioning full machines, we provide purpose‑built, serverless sandboxes that are easy to integrate and operate while still covering real‑world needs (dependencies, secrets, scheduling, logs/results, audit). ## How YepCode fits: secure execution + simple I/O **YepCode Run** gives you a serverless execution plane for JavaScript and Python that’s built on isolated sandboxes with automatic dependency installation, timeouts, logs, and return values. You send code; it runs safely; you get results. No Dockerfiles to maintain and no host exposure. For handling inputs and outputs across runs or tools, **YepCode Storage** provides secure, API‑driven file storage. Use it to upload inputs (CSVs, PDFs, images), keep intermediate artifacts, and persist results. Each YepCode execution can receive [input parameters](/docs/processes/input-params/) and [return results](/docs/processes/source-code/#return-value) for structured data flow. ### Developer‑first by design * **Dependencies out of the box**: import any npm/PyPI package; installs are handled for you per execution. * **Team Variables & Secrets**: manage centrally; values are injected securely at runtime without exposing them to the LLM. * **Scheduling**: trigger executions as cron jobs or on a schedule for recurring jobs and automations. * **Results & logs**: stream logs, capture return values, and retrieve artifacts programmatically. * **Enterprise‑grade audit**: who ran what and when, with execution metadata for compliance. ### Complete workflow: upload, process, and download Here’s a complete example showing how to upload a file, process it securely with YepCode Run, and download the results: * JavaScript ```js const { YepCodeRun, YepCodeStorage } = require("@yepcode/run"); const fs = require("fs"); const runner = new YepCodeRun({ apiToken: "" }); const storage = new YepCodeStorage({ apiToken: "" }); async function processData() { // 1. Upload input file await storage.upload("inputs/data.csv", fs.createReadStream("./data.csv")); // 2. Execute code that processes the file const execution = await runner.run( `async function main() { const fs = require("fs"); const csv = require("csv-parser"); // Download and process the CSV const stream = await yepcode.storage.download("inputs/data.csv"); const results = []; return new Promise((resolve) => { stream.pipe(csv()) .on('data', (data) => results.push(data)) .on('end', async () => { // Process data and create summary const summary = { totalRecords: results.length, processedAt: new Date().toISOString() }; // Upload processed results await yepcode.storage.upload( "outputs/summary.json", new Blob([JSON.stringify(summary, null, 2)], { type : 'application/json' }) ); resolve(summary); }); }); } module.exports = { main };`, { onLog: (log) => console.log(`${log.timestamp} ${log.level}: ${log.message}`), onFinish: (returnValue) => console.log("Processing finished:", returnValue), onError: (error) => console.error("Error:", error), } ); await execution.waitForDone(); // 3. Download the processed results const resultStream = await storage.download("outputs/summary.json"); resultStream.pipe(fs.createWriteStream("./processed-summary.json")); console.log("Workflow completed!"); } processData(); ``` * Python ```py from yepcode_run import YepCodeRun, YepCodeStorage, YepCodeApiConfig runner = YepCodeRun( YepCodeApiConfig( api_token="" ) ) storage = YepCodeStorage( YepCodeApiConfig( api_token="" ) ) def process_data(): # 1. Upload input file with open("data.csv", "rb") as f: storage.upload("inputs/data.csv", f) # 2. Execute code that processes the file execution = runner.run( """def main(): import pandas as pd import json import io # Download and process the CSV content = yepcode.storage.download("inputs/data.csv") df = pd.read_csv(io.BytesIO(content)) # Process data and create summary summary = { "totalRecords": len(df), "processedAt": pd.Timestamp.now().isoformat() } # Upload processed results summary_json = json.dumps(summary).encode() yepcode.storage.upload("outputs/summary.json", io.BytesIO(summary_json)) return summary""", { "onLog": lambda log: print(f"{log.timestamp} {log.level}: {log.message}"), "onFinish": lambda return_value: print( "Processing finished:", return_value ), "onError": lambda error: print("Error:", error), }, ) execution.wait_for_done() # 3. Download the processed results content = storage.download("outputs/summary.json") with open("processed-summary.json", "wb") as f: f.write(content) print("Workflow completed!") process_data() ``` ### Putting it together: safe agent workflows An end‑to‑end pattern we recommend for agentic systems: 1. **Upload inputs to Storage** (e.g., CSV, PDF, prompt context files). 2. **Generate code** with your LLM (JS or Python) to process those inputs. 3. **Execute with YepCode Run** in an isolated sandbox; capture logs and return values. 4. **Persist outputs to Storage** (artifacts, JSON summaries, charts) for downstream tools. 5. **Audit and retry** with full logs; iterate safely without exposing your host. This approach gives you the flexibility of dynamic, LLM‑generated code with the safety of ephemeral, resource‑limited sandboxes—and predictable file I/O. ## Why this matters now As agents take on higher‑impact tasks, the execution surface becomes an organizational risk. Following secure‑by‑default patterns—sandboxed execution and controlled file I/O—lets you ship faster without compromising safety. If you’re exploring AI Agent platforms like Smolagents, Autogen, CrewAI, or event no-code tools agents like n8n, zapier or make, keep going—and consider using YepCode Run as your execution plane plus YepCode Storage for reliable I/O. You’ll get modern developer ergonomics with security that scales. # An overview of YepCode technology stack > YepCode is a platform to automate your processes and integrate other tools just by coding in a web browser. Discover all the technology stack behind this awesome tool. ## Discover YepCode technology stack ***Divide et impera… microservices to the rescue!*** The planning process for building the **YepCode technology stack** was thorough and deliberate. We had no doubt about the benefits of creating YepCode using [microservices](https://martinfowler.com/articles/microservices.html) instead of a monolithic architecture: **scalability**, **resource efficiency**, **automation** (CI/CD), **reliability**, **isolated and bulletproof environments**, and **maintainability**. In the following image, you can see **YepCode’s current microservices architecture diagram**. In the next sections, we’ll provide an overview of each service, explaining the technologies, responsibilities, and communications between them. ![YepCode services stack](/_astro/yepcode-stack.BGKWtA7W_Z16TQM7.webp) ### Before starting, a little bit of DDD, testing, hexagonal architecture, git branching model, CI/CD… As you might expect, **in YepCode we are code lovers**, and **we like to create software using high-quality standards**. Some of the principles we apply on every YepCode layer are: * **DDD:** We need to understand that software is not just about code. **Domain-Driven Design** ensures that every person involved in the project speaks the same language. Sometimes it’s hard to communicate, but once that barrier is broken, information flows freely and doesn’t get lost. **DDD provides a guide for both strategic and tactical design.** Strategic focus centers on business values, while tactical focus builds a battle-tested domain model. DDD also **emphasizes practices like continuous integration.** This ensures the integrity of the entire project, allowing potential problems to be detected early. * **Testing:** We want every piece of code to be fully tested. We know that’s somewhat idealistic, but we do our best. Every feature has its unit, integration, acceptance, and smoke tests. **Developing a function without any test is not acceptable for us**. * **Git branching model**: Another of our main goals is **agility.** For that reason, we chose [trunk-based development](https://trunkbaseddevelopment.com/) as our branching model. With this model, **we ensure that we work in the main branch almost all the time.** And, of course, the main branch is always production-ready. * **CI/CD**: We rely on [GitHub](https://github.com/features/actions) to implement our CI/CD cycles. With each [pull request](https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests), all tests are executed. After merging into the **main** branch, new **Docker images are generated and published** to our private Docker registry. Finally, our **Kubernetes cluster** picks them up to **deploy the new versions**. ### Hey, are you still there? Don’t lose focus. We are talking about the YepCode technology stack, so let’s start with our web-client **YepCode users only need a web browser to use the platform**. We chose [Next.js](https://nextjs.org/) as our frontend framework because we love it! You probably already know this, but Next.js is based on [React.js](https://reactjs.org/). It helps us with tedious initial and production [React.js](https://reactjs.org/) configurations. **This is one of our core technologies for other projects**, and the team has extensive expertise using it. In the past, we worked extensively with [Ruby on Rails](https://rubyonrails.org/) and [JEE template frameworks](https://www.thymeleaf.org/). But in this case, **we picked this framework that allows us to quickly achieve any needed feature**. We also use [Tailwind CSS](https://tailwindcss.com/) to help us manage styles. We could use a preprocessor directly like Sass, but that requires a lot of effort to start and maintain. **[Tailwind CSS](https://tailwindcss.com/) does all the heavy lifting for us**. **With very little effort, we maintain clean code and stay very agile.** We are fortunate to have a **great design team that ensures that user experience and design are under control in every change**. To achieve this, we rely on [Figma](https://www.figma.com/), which allows us to share and discuss any new feature before starting to implement it. ### And, what about the APIs? When it came time to choose our API approach, we realized that different use cases require different solutions. **We decided to implement a dual API strategy** that provides the best of both worlds: **Frontend API (GraphQL)**: Our internal frontend uses a [GraphQL API](https://graphql.org/) that we’re very comfortable with. **We enjoy the flexibility that queries and mutations provide**, allowing us to request only the necessary information in each React component. This approach gives us the exact data we need without over-fetching or under-fetching. **REST API**: For external integrations, our SDKs and third-party developers, we provide a comprehensive [REST API](https://cloud.yepcode.io/api/rest/public/swagger-ui/index.html) that follows standard REST principles. This API is fully documented with Swagger UI and allows external clients to schedule executions, create processes, review logs, and more. **This dual approach ensures that we have the right tool for each job** - GraphQL for our internal frontend’s complex data requirements and REST for external integrations that need a more traditional, well-documented API approach. **MCP Tools API**: For AI agents and automation workflows, we provide a [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) Tools API that enables seamless integration with AI assistants and LLMs. This API allows AI agents to interact with YepCode processes, execute code, and manage workflows programmatically, opening up powerful automation possibilities. ### YepCode integrations To make YepCode even more accessible and powerful, we’ve developed a comprehensive set of integration tools that enable seamless connectivity with various platforms and workflows: **yepcode-run sdk**: It provides a simple and intuitive way to execute code in YepCode’s secure sandbox environment from JavaScript or Python applications. This SDK enables developers to run AI-generated code safely, execute custom scripts, and leverage YepCode’s processing capabilities from their preferred programming language. See [yepcode-run (Python)](https://pypi.org/project/yepcode-run/) and [@yepcode/run (JavaScript)](https://www.npmjs.com/package/@yepcode/run) for more information. YepCode Run SDK also includes a full YepCode API client, so you can use YepCode from your own code. **MCP Server**: Our Model Context Protocol server implementation that allows AI agents and LLMs to interact directly with YepCode. This server exposes YepCode’s capabilities as MCP tools, enabling AI assistants to execute processes, manage workflows, and access YepCode’s features through a standardized protocol. See [MCP Server blog post](/blog/yepcode-mcp-user-defined-tools-ai-automation/) for more information. These integration tools ensure that YepCode can be easily incorporated into existing workflows, regardless of the technology stack or platform being used. ### The backend microservices Our backend architecture is built around a sophisticated microservices design that separates concerns between control and execution planes. This separation ensures optimal performance, scalability, and maintainability. #### Control plane The control plane manages the orchestration and coordination of all YepCode operations: * **API**: The primary entry point for all external requests, this JEE web application is built on the Spring framework stack. It serves GraphQL API, REST API and MCP Tools API, handles authentication, rate limiting, and **receives external webhook requests**. As the only service exposed to the internet, it implements comprehensive security measures and request validation. * **Engine**: The central orchestrator that manages the execution lifecycle. It **reads and stores from the database any information that the executors may need**, maintains execution state, and coordinates between different microservices. The engine subscribes to message queues where executors publish events (logs, execution results, etc.) and publishes events for executions that need to be processed. * **Scheduler**: This critical microservice manages all time-based executions and cron jobs. It handles process scheduling using both fixed start times and cron expressions, ensuring reliable execution timing. The scheduler prepares execution contexts and coordinates with the engine to trigger processes at the appropriate times. * **YepCode Storage**: Manages persistent file storage for user executions with enterprise-grade security. It provides a unified interface for storing and retrieving files, supporting multiple cloud storage providers like AWS S3 and Google Cloud Storage. The service ensures data durability, availability, and secure access patterns. See [YepCode Storage](/docs/storage/) for more information. #### Execution plane The execution plane handles the actual processing of user code in isolated, secure environments: * **Instances Operator**: This intelligent microservice orchestrates the execution infrastructure by dynamically managing the number of execution instances based on demand. It continuously monitors performance metrics and automatically scales instances up or down to optimize resource utilization and ensure optimal performance. The operator also performs health checks on running instances and handles rolling updates to deploy new versions without service interruption, ensuring zero-downtime deployments. * **Executor Manager**: Acts as the execution coordinator, receiving execution requests from the engine and managing the lifecycle of process executions. * **Executor**: The core execution engine that runs user processes in isolated Firecracker microVMs. Each executor instance provides a secure, sandboxed environment where user code can run safely without affecting other processes or the underlying infrastructure. * **Dependencies Manager**: Manages the complex dependency ecosystem for user processes. It downloads and caches dependencies, ensuring they’re available to executors when needed. * **YepCode Datastore**: Provides persistent key-value storage for user processes, enabling data sharing between executions and maintaining state across process runs. See [YepCode Datastore](/docs/datastore/) for more information. ### How AAA has been solved? We don’t like to reinvent the wheel, and since **we have been using [Keycloak](https://www.keycloak.org/) as an identity and access management solution** for years, we’re continuing with that approach. This open-source project is our core for authentication, authorization, and accounting. ### Persistence: MongoDB to the rescue Another significant decision (perhaps one of the greatest dilemmas in every software application) is which solution to use for data storage. A relational database could be used, but the documents we have to store are quite large, and the most common retrieval is by key. **So, we decided to choose a NoSQL database that stores information in JSON documents as the best option.** Among all the excellent software projects that fit that NoSQL approach, we picked [MongoDB](https://www.mongodb.com/). This choice was primarily driven by our experience with it and because it’s one of the core solutions present in the high availability cluster where YepCode runs. ### And what about the metal that allows running all this stuff We have also been working with [Docker](https://www.docker.com/) and [Kubernetes](https://kubernetes.io/) solutions for years, and we’re very comfortable with them. **So with YepCode, we continue with those DevOps solutions.** In our cluster, we enjoy high availability features. **Each microservice can scale to accommodate any increased workload.** Additionally, we have high availability and redundancy in the persistence layer, but we prefer to tell you about this in another article 🤓 ### Security and Sandboxing: Firecracker for isolated executions Security is paramount when running user-generated code in a multi-tenant environment. **We solved the sandboxing challenge using [Firecracker](https://firecracker-microvm.github.io/)**, an open-source virtualization technology that enables secure and fast microVMs. **Firecracker provides the perfect balance between security and performance.** Each process execution runs in its own isolated microVM, ensuring complete isolation between different users and processes. This approach gives us: * **Complete isolation**: Each execution runs in its own virtual machine, preventing any cross-contamination between processes * **Fast startup times**: Firecracker microVMs start in milliseconds, much faster than traditional VMs * **Resource efficiency**: Lightweight virtualization that doesn’t consume excessive resources * **Security by design**: Built-in security features that prevent unauthorized access to the host system **This sandboxing approach ensures that even if malicious code is executed, it cannot access other users’ data or compromise the underlying infrastructure.** The microVM approach provides the same level of security as traditional VMs but with the performance characteristics of containers. Our executors leverage Firecracker to create these isolated environments dynamically, ensuring that every process execution is completely secure and isolated from the rest of the system. # Run Any NPM or PyPI Package in n8n Using YepCode > Discover how to run any NPM or PyPI package in n8n using YepCode. Execute custom JavaScript or Python code and go beyond built-in nodes to unlock unlimited automation possibilities. **n8n’s built-in nodes are powerful, but what happens when you need something specific that doesn’t exist?** That’s where YepCode comes in. Unlike other no-code platforms that limit you to predefined functions, YepCode lets you run **any NPM or PyPI package** with custom JavaScript or Python code directly in your n8n workflows. > **The key differentiator:** You’re not limited to built-in functions or a curated list of packages. If it’s on npm or PyPI, you can run it. ## What is the Run Code Operation? The **Run Code** operation is YepCode’s most flexible feature in n8n. It allows you to: * **Run custom JavaScript or Python code** directly in your workflow * **Use any NPM package** (for JavaScript) or **any PyPI package** (for Python) * **Transform data** with complex logic that would require multiple n8n nodes * **Call APIs** that don’t have native n8n integrations * **Process files** and handle binary data * **Run AI-generated code** on the fly ## Setup Prerequisites To use YepCode’s Run Code operation in n8n, you’ll need: 1. A [YepCode account](https://cloud.yepcode.io/) 2. An n8n Cloud account or self-hosted n8n installation For detailed setup instructions, check out our [complete n8n integration guide](/blog/n8n-yepcode-combined-build-amazing-workflows). ### Setting up YepCode credentials To connect n8n with YepCode, you’ll need to create API credentials: 1. In your YepCode account, go to **Settings > API Keys** 2. Create a new API key with appropriate permissions 3. In n8n, when configuring the YepCode node, click **“Create New”** under credentials 4. Enter your YepCode API key 5. Test the connection to ensure everything works > **Need help with the full setup?** Check out our [complete n8n integration guide](/blog/n8n-yepcode-combined-build-amazing-workflows) for detailed step-by-step instructions. ## Complete Example: Data Processing ![](/_astro/n8n_run_code_config.CR01RTPc_ZrbdGA.webp) Let’s walk through a complete example that shows all the key concepts. This example processes n8n data using the Luxon date library: ```javascript // Import any npm package - YepCode will install it automatically const { DateTime } = require("luxon"); const { n8n } = yepcode.context.parameters; const results = []; for (const item of n8n.items) { results.push({ ...item.json, processedAt: DateTime.now().toISO(), }); } // Access n8n metadata - check all available fields at: https://docs.n8n.io/code/builtin/n8n-metadata/ console.log("Environment:", n8n.metadata); console.log("Resume URL:", n8n.metadata["$execution"].resumeUrl); return results; ``` ### Breaking Down the Example **1. Package Import:** ```javascript const { DateTime } = require("luxon"); ``` * YepCode automatically installs any npm package you require * No need to manage dependencies or package.json files * Just use `require()` or `import` and it works If you are connecting to some private service (API’s, databases, storage systems, etc.), do not include any sensitive information in the code, use YepCode [Team Variables](/docs/processes/team-variables) instead. **2. Accessing n8n Data:** ```javascript const { n8n } = yepcode.context.parameters; ``` * All n8n data is available through `yepcode.context.parameters.n8n` * `n8n.items` contains the data from previous nodes * Each item has a `json` property with the actual data **3. Processing Data:** ```javascript const results = []; for (const item of n8n.items) { results.push({ ...item.json, processedAt: DateTime.now().toISO(), }); } ``` * Loop through each item from the previous n8n node * Use the Luxon library to add timestamps * Return the processed data for the next node **4. Accessing n8n Metadata:** ```javascript console.log("Environment:", n8n.metadata); console.log("Resume URL:", n8n.metadata["$execution"].resumeUrl); ``` * Access execution metadata, environment variables, and more * Useful for debugging and conditional logic * Full documentation available at [n8n metadata docs](https://docs.n8n.io/code/builtin/n8n-metadata/) **5. Returning Results:** ```javascript return results; ``` * The returned data becomes available to the next n8n node * Can return objects, arrays, or any JSON-serializable data ## When to Use Run Code **Use Run Code when:** * You need quick, one-off transformations * You want to run specific packages not available elsewhere * You’re prototyping or testing ideas * The logic is simple and doesn’t need versioning > **Note:** For reusable business logic with version control and team collaboration, consider using YepCode’s Run Process operation instead. > **📚 Official Documentation:** For the complete technical reference, visit the [YepCode n8n node repository](https://github.com/yepcode/n8n-nodes-yepcode?tab=readme-ov-file#2-run-code) on GitHub. ## Conclusion The Run Code operation transforms n8n from a no-code platform into a **no-code + full-code hybrid**. You get the visual workflow benefits of n8n with the unlimited power of running any package. **Ready to unlock unlimited automation possibilities?** Start with the example above and see how YepCode can revolutionize your n8n workflows. Happy coding! 🚀 # Introducing YepCode Storage: Secure File Management for Your Automation Workflows > We're excited to announce YepCode Storage - a robust file storage system that revolutionizes how you handle files in your automation workflows. Upload, process, and share files seamlessly across your processes and external systems. 🚀 **Managing files in automation workflows just got a whole lot easier!** We’re thrilled to announce **[YepCode Storage](/docs/storage)** — a powerful, secure file management system that transforms how you handle files within your automation processes. Whether you’re processing documents, analyzing data, or sharing files between workflows, YepCode Storage provides the robust foundation you need. ## **What is YepCode Storage?** YepCode Storage is a robust file storage system designed specifically for automation workflows inside YepCode. It provides a simple yet powerful way to: ✅ **Upload files** from external sources or process outputs ✅ **Download files** for processing and analysis within your workflows ✅ **Share files** securely between different processes ✅ **Store temporary results** that need to persist beyond single executions ✅ **Process documents** with AI, extract data, or perform transformations ## How does YepCode Storage work? ### **In your processes source code** You may use YepCode Storage in your processes source code with the `yepcode.storage` helper: * JavaScript ```js // Upload a stream await yepcode.storage.upload("path/myfile.txt", anyStream); // List files const files = await yepcode.storage.list(); // Download a file const stream = await yepcode.storage.download("path/myfile.txt"); // Delete a file await yepcode.storage.delete("path/myfile.txt"); ``` * Python ```py # Upload a stream yepcode.storage.upload("path/myfile.txt", f) # List files files = yepcode.storage.list() # Download a file content = yepcode.storage.download("path/myfile.txt") # Delete a file yepcode.storage.delete("path/myfile.txt") ``` ### **From any external system** YepCode Storage is also available through our [REST API](/docs/api). You can use it to upload, download, list and delete files from any external system. ![](/_astro/yepcode-storage-api.shwI6zoZ_2qvsGe.webp) ### **Using our YepCode Run SDK** YepCode Storage is also available through our YepCode Run SDK, both available in [JavaScript](https://www.npmjs.com/package/@yepcode/run) or [Python](https://pypi.org/project/yepcode-run/): * JavaScript ```js const { YepCodeStorage } = require('@yepcode/run'); const fs = require('fs'); const storage = new YepCodeStorage({ apiToken: '****' }); // Upload a file (using Node.js stream) await storage.upload('path/myfile.txt', fs.createReadStream('./myfile.txt')); // List files const files = await storage.list(); console.log(files); // Download a file const stream = await storage.download('path/myfile.txt'); stream.pipe(fs.createWriteStream('./downloaded.txt')); // Delete a file await storage.delete('myfile.txt'); ``` * Python ```py from yepcode_run import YepCodeStorage, YepCodeApiConfig storage = YepCodeStorage( YepCodeApiConfig(api_token='your-api-token') ) # Upload a file with open('myfile.txt', 'rb') as f: obj = storage.upload('myfile.txt', f) print('Uploaded:', obj.name, obj.size, obj.link) # List all storage objects objects = storage.list() for obj in objects: print(obj.name, obj.size, obj.link) # Download a file content = storage.download('myfile.txt') with open('downloaded.txt', 'wb') as f: f.write(content) # Delete a file storage.delete('myfile.txt') ``` ### **From any AI Agent using our MCP server** Here’s where things get really exciting: **YepCode Storage is also available as MCP tools** in our [MCP server](https://github.com/yepcode/mcp-server-js?tab=readme-ov-file#storage-management), making it incredibly powerful when combined with AI agents and our `run_code` tool. Imagine this conversation with an AI agent: > **You:** “Process this sales CSV file with a Python script to calculate regional performance and generate insights” > **AI Agent:** *Uses MCP tools to:* > > 1. Upload your CSV file to YepCode Storage > 2. Generate and execute Python code via `run_code` tool to process the data > 3. Create visualizations and summaries > 4. Store results back to YepCode Storage > 5. Provide you with download links and insights ![](/_astro/yepcode-storage-agent.C7GY9X7N_Z8mkPz.webp) This combination of **YepCode Storage + MCP tools + run\_code** creates an incredibly powerful environment where AI agents can: * **Handle file-based tasks** end-to-end without manual intervention * **Process complex data** using the full power of Python/JavaScript ecosystems * **Store and retrieve results** securely in the cloud * **Chain multiple operations** across different files and datasets ## **Key Use Cases** ### **📄 Document Processing** * Upload contracts, invoices, or forms for automated data extraction * Process images with OCR or AI for content analysis * Convert documents between formats (PDF, Word, Excel) ### **📊 Data Analysis & Reporting** * Store CSV files for periodic data processing * Generate reports and charts from uploaded datasets * Create dashboards from real-time data uploads ### **🔄 Cross-Process File Sharing** * Share processed results between different automation workflows * Create file repositories for team collaboration * Build file-based triggers for complex automations ### **💾 Backup & Archival** * Store important process outputs for compliance * Create automated backup workflows * Archive historical data for future analysis ## **Ready to Transform Your File Workflows?** YepCode Storage is available now every of our plans, and we have also allowed to use some local storage during executions. Check our [plans and limits](/docs/plans-and-limits) to see which one fits your needs. Start building with YepCode Storage today and discover how seamless file management can unlock new automation possibilities for your business. # Supercharge Your n8n AI Agents with YepCode: Execute Custom Code and Processes Seamlessly > Learn how YepCode's new n8n connector revolutionizes AI agent workflows by enabling secure code execution and custom process automation. See it in action with our detailed video demonstration. ## Breaking Down Barriers: AI Agents Meet Custom Code Execution **What if your n8n AI agents could write and execute code on demand?** What if they could tap into your existing YepCode processes with just a prompt? That’s exactly what our new **YepCode n8n connector** makes possible. We’re excited to share a comprehensive video demonstration that showcases how this game-changing integration transforms what’s possible with n8n agents. > **Watch the full demo video above** to see real-world examples of AI agents generating and executing Python/JavaScript code, accessing custom APIs, and processing complex data—all triggered by simple natural language prompts. ## What Makes This Integration Revolutionary? The YepCode n8n connector introduces **two powerful tools** that extend your AI agents’ capabilities far beyond traditional no-code limitations: ### 🚀 **Run Code Tool**: LLM-Generated Scripts on Demand Your AI agents can now: * **Generate custom Python or JavaScript code** to solve any task * **Execute scripts securely** within YepCode’s infrastructure * **Access any npm or PyPI packages** for advanced functionality * **Handle complex data transformations** that would be impossible with standard n8n nodes ### ⚡ **Run Processes Tool**: Tap Into Your Existing Automations Your agents can also: * **Execute any YepCode process** from your account * **Pass dynamic parameters** generated by the LLM * **Access custom modules and API integrations** you’ve already built * **Leverage advanced authentication** and secure credential management ## See It in Action: Real Demo Scenarios In our demo video, you’ll witness two compelling use cases that demonstrate the connector’s power: ### **Scenario 1: GitHub Repository Analysis** Watch as an AI agent: * Receives a simple prompt: *“Get statistical information about the n8n GitHub repo”* * **Automatically generates Python code** to interact with GitHub’s API * **Executes the script** and returns detailed repository statistics * **All without any manual coding** from the user ### **Scenario 2: HR System Integration** See how the agent: * Connects to a **custom HR platform process** built in YepCode * **Retrieves employee vacation data** for a specific date range * **Handles authentication and API complexity** seamlessly through existing YepCode modules * **Delivers formatted results** ready for further processing ## Why to use this connector Traditional no-code platforms hit walls when faced with: * **Complex data processing requirements** * **Custom API integrations** not covered by existing nodes * **Advanced calculations** and algorithms * **Dynamic code generation** based on changing requirements **The YepCode connector eliminates these with these technical benefits:** * **🔒 Secure Execution**: All code runs in YepCode’s isolated environment * **📊 Full Visibility**: Review generated code, execution logs, and results * **🔄 Version Control**: Every execution is tracked and auditable * **⚡ High Performance**: Leverage YepCode’s optimized infrastructure * **🔌 Easy Setup**: No complex configuration or additional servers required ## Get Started Today Ready to give your n8n agents superpowers? The YepCode connector is available now: 1. **Install the connector** from the n8n community nodes 2. **Set up your YepCode credentials** in n8n 3. **Add YepCode tools** to your agent configuration 4. **Start experimenting** with code-generating prompts **Don’t miss our detailed walkthrough video**—it’s packed with practical examples, best practices, and insider tips that will help you make the most of this powerful integration. *The future of AI automation is here, and it speaks both natural language and code.* # Zapier + YepCode: Bring the Full Power of Code to Your Zaps > Extend your Zapier workflows with the power of serverless functions. The new YepCode connector lets you run custom code securely, using any NPM or PyPI library — all without managing infrastructure. No-code tools are amazing — until they’re not. You’ve been there: you’re building a Zapier workflow and hit a wall. You need to transform a payload, query a custom API, or run some logic that’s just too complex for built-in steps. That’s exactly where **YepCode Run** comes in — and we’re excited to announce that it’s now available **directly inside Zapier** 🎉 ![](/_astro/6847f935b623126c060d8dc1_1.CQ06beJQ_ZQ4y4c.webp) Use the Run Code tool to execute any LLM generated code or the Run Process tool to start executions of your existing processes ### **⚡ What’s new?** With the new [**YepCode Run connector**](https://zapier.com/apps/yepcode/integrations), you can now: ✅ Execute any custom serverless function right from your Zaps ✅ Define input parameters and map them easily from previous steps ✅ Use LLM-generated or prebuilt code to connect with APIs, query databases, transform files, and more ✅ Rely on any NPM or PyPI library — YepCode handles all the infrastructure and dependencies This means **you get the power of full-code** without leaving the Zapier ecosystem. ![](/_astro/6847f95e1e34ba2b8efe4c6c_2.DT9T_vuO_1D3VNH.webp) Write or map your code from other Zap Step. You may use any NPM or PyPI dependency ![](/_astro/6847f985977199fb03169d92_3.D0GkJ8hr_Z12LzcJ.webp) Input parameters from your process are available in the Zapier connector to be mapped ### **🤖 Great fallback for AI agents** If you’re exploring AI agents inside Zapier (like with OpenAI or Claude), this is a game-changer. Let’s say your agent can generate the right script — but it needs somewhere to run it. Now it can. Securely. Reliably. With YepCode, agents get a powerful execution environment that makes it easy to go from suggestion to action — from “this is the code” to “done.” ![](/_astro/6847f96a0d1c99ed1c31ac65_5.BlmxLKcM_Z114zqL.webp) Use the tools in your Zapier Ageents offering them a fallback option to solve unknown tasks ![](/_astro/6847f976ff82e1546b204d53_6.YHk05VQH_b00Gz.webp) Use the execution results to rewrite the code and run it again ### **🔧 Ideal for:** * Custom API integrations * AI-powered automation * Data transformations * Workarounds when Zapier’s native actions fall short * Teams who need flexibility without building infra 👉 **Ready to give it a spin?** We’d love to hear what you build — and we’re open to co-develop proof-of-concept automations for interesting use cases. Let’s push automation further, together. With YepCode, you’re always just one script away from unlocking anything. # Integrating YepCode with crewAI: Build Multi-Agent AI Workflows That Run Real Code > Discover how to combine crewAI and YepCode to build collaborative, multi-agent AI workflows that don’t just reason—they act. In this hands-on guide, you’ll set up a fun asteroid impact scenario where agents calculate, automate, and generate real results by running Python or JavaScript code in the cloud. Perfect for anyone interested in next-level AI automation and practical agent orchestration. Modern AI agents can do more than just chat—they can reason, collaborate, and even execute real code to solve complex tasks. > **What if you could combine multi-agent intelligence with cloud-powered code execution?** In this post, you’ll see how to connect [crewAI](https://crewai.com) and [YepCode](https://yepcode.io/) to build a workflow where agents not only think, but act—automating a real-world scenario from start to finish. ### Motivation & Use Case Why multi-agent systems? Because real-world problems are rarely solved by a single expert—they require collaboration, specialization, and the ability to take action. > Imagine automating scientific analysis and reporting, end-to-end, with agents that both think and do. In this demo, we tackle a scenario with real stakes: assessing the impact of an asteroid hitting Earth. (Okay, it’s a fun and slightly tongue-in-cheek example—but perfect for showing how agents can combine reasoning, data, and automation to deliver results you can use.) ![](/_astro/68481003aaab63370759726e_Screenshot-2025-06-10-at-11.45.56.NBkRslKo_ZMNWYw.webp) *No planets were harmed in the making of this post.* ### Tech Stack Overview This project brings together two powerful tools: \- **crewAI**: Lets you build teams of AI agents that can reason, collaborate, and delegate tasks—just like a real crew. \- **YepCode**: A cloud platform where agents can run real code, automate workflows, and interact with APIs on the fly. > **Together, they let your agents not only think, but act.** ### Scenario: Asteroid Impact Assessment Our agents are on a mission: figure out what would happen if an asteroid hit Earth, and write up a dramatic report. \- **Asteroid Data Scientist**: Crunches the numbers and calculates the impact. \- **Impact Reporter**: Turns the data into a story that’s fun (and maybe a little scary) to read. #### Project Setup Getting started is easy: 1\. [**Clone the repo**](https://github.com/yepcode/crewai-yepcode-demo) and create a virtual environment. 2\. **Install dependencies** with a couple of commands. 3\. **Copy \`.env.example\` to \``.env`\`** and add your API keys. > You’ll need Python 3.10–3.12, plus a free YepCode and OpenAI account. #### Defining Agents and Tasks Agents and their goals are defined in simple YAML files: \- `agents.yaml`: Who does what (e.g., Data Scientist, Reporter) \- `tasks.yaml`: What needs to be done, and in what order > Tweak these files to create your own agent teams and workflows! #### Integrating YepCode For this scenario, we’re using the [YepCode MCP server](https://github.com/yepcode/mcp-server-js)—an ideal fit when agents need to run real code and automate complex tasks. While CrewAI lets you [create custom tools](https://docs.crewai.com/concepts/tools) directly in your project, using YepCode MCP is even more powerful: * You can define, update, and manage your tools in YepCode’s platform. * Instantly expose new tools to your agents with just a line of code—no redeploy needed. * Perfect for scientific tasks, data processing, or any workflow where flexibility and cloud execution matter. In this project, the **Asteroid Data Scientist** agent uses YepCode MCP to perform calculations. By default, YepCode MCP provides a `run_code` action that can execute any Python or JavaScript code—so your agent can dynamically generate and run code to solve the problem, not just call a fixed API. > You can also create your own custom tools in YepCode—like a dedicated “Calculate Asteroid Impact Energy” process. (I’ll show how to add and use a custom tool in [this post](https://yepcode.io/blog/yepcode-mcp-user-defined-tools-ai-automation), with the code and setup!) This flexibility is what makes YepCode MCP a perfect match for agent-based workflows. ### Running the Workflow Just run one command: You will be prompted with all the crewAI workflow steps in the terminal, showing how agents collaborate to solve the task. ![](/_astro/68480fa490ab6ab262068957_Screenshot-2025-06-10-at-11.45.17.RUISjE4P_Z16mYgt.webp) *Steps taken by the crew* Once the workflow ends you’ll get a file like `asteroid_impact_report.md` with the outcome. ![](/_astro/68481003aaab63370759726e_Screenshot-2025-06-10-at-11.45.56.NBkRslKo_ZMNWYw.webp) *Preview of asteroid\_impact\_report.md file* ### Conclusion By combining crewAI and YepCode, you unlock a new level of AI automation—where agents can collaborate, reason, and execute real code to solve real problems. [GitHub Repository](https://github.com/yepcode/crewai-yepcode-demo)‍ > Try the repo, remix the agents, and imagine what you could automate next!Curious to try this for your own API or use case? [Contact us](https://yepcode.io/contact) — we’d love to hear what you’re building. # How to Create and Use Custom MCP Tools in YepCode > Discover how to create and expose your own user-defined MCP tools in YepCode, making them instantly available to AI platforms like Cursor, Claude, and OpenAI. This guide walks you through building, configuring, and connecting Python or JavaScript tools for secure, scalable, cloud-powered automation—no server setup required. > **Turn your code into AI-powered tools.** YepCode MCP tools let you turn any Python or JavaScript function into a cloud-powered action—designed to be executed by any AI platform (like Cursor, Claude, or OpenAI) once your MCP server is configured and accessible. *If you can code it, you can make it a tool—data processing, API calls, or real-world actions. The possibilities are endless, especially when LLMs can trigger your logic on demand.* In this post, you’ll learn how to: * Build a custom MCP tool in YepCode * Define its inputs and outputs * Use it from automations or with frameworks like crewAI For more about MCP tools, see the [official documentation](https://modelcontextprotocol.io/docs/concepts/tools). ### **Why MCP Custom Tools?** YepCode MCP tools are more than just code—they’re reusable, cloud-executed functions that can be called from anywhere, by anyone (or anything) you authorize. * ‍**Reusable:** Write your logic once, use it in many workflows or projects. * **Cloud-powered:** No need to redeploy or manage infrastructure—just update your tool in YepCode. * **Empower LLMs and agents:** Let AI models and automations trigger real-world actions, not just make suggestions. > Imagine an LLM that can not only answer questions, but also fetch data, run calculations, or trigger workflows—MCP tools make this possible. > With MCP tools, your code becomes a living API—ready to power automations, agent workflows, and LLM-driven solutions. ### **Prerequisites** Before you start, make sure you have: * A [YepCode account](https://cloud.yepcode.io/) (free tier is enough) * Basic Python or JavaScript skills * An idea for a tool (e.g., a calculation, API call, or data transformation) > No local environment or server setup required—everything runs in the cloud! ### **Step-by-Step: Creating a YepCode Custom MCP Tool** Follow this checklist to create your first MCP tool: 1. Create a new process in YepCode ([official docs](/docs/processes)) 2. Add your logic in Python or JavaScript 3. Define your input and output parameters 4. **Add the** `mcp-tool` **tag** in the process settings 5. Save and version your tool as usual > If you don’t tag your process as `mcp-tool`, it won’t show up as a mcp tool for LLMs or agents to use! Now your tool is ready to be discovered and called by AI agents, automations, or LLMs. #### **Example: Asteroid Impact Energy Calculator** > You can edit and test your tool right in the YepCode web UI. Copy-paste this code and try it with your own parameters! Here’s a Python example that calculates the energy released by an asteroid impact, given its diameter, speed, and angle. ```py import math def calculate_impact_energy(diameter_km, speed_kms, impact_angle_degrees): # Convert diameter to meters diameter_m = diameter_km * 1000 # Calculate mass assuming a density of 3000 kg/m³ for stony asteroids radius_m = diameter_m / 2 volume_m3 = (4 / 3) * math.pi * radius_m**3 density_kgm3 = 3000 # kg/m³ for stony asteroid mass_kg = volume_m3 * density_kgm3 # Calculate kinetic energy in Joules speed_ms = speed_kms * 1000 kinetic_energy_joules = 0.5 * mass_kg * speed_ms**2 # Convert Joules to megatons of TNT (1 megaton TNT ≈ 4.184e+15 Joules) impact_energy_megatons = kinetic_energy_joules / (4.184e15) return impact_energy_megatons try: parameters = yepcode.context.parameters diameter_km = parameters["diameter_km"] impact_speed_kms = parameters["impact_speed_kms"] impact_angle_degrees = parameters["impact_angle_degrees"] # Calculations impact_energy = calculate_impact_energy( diameter_km, impact_speed_kms, impact_angle_degrees ) return impact_energy except KeyError as e: return { "body": { "message": f"Missing required parameter: {e.args[0]}", "solution": "Please provide all required parameters in the request body as a JSON object. The required parameters are: diameter_km, impact_speed_kms, impact_angle_degrees", }, "status": 400, } ``` **Parameters:** * `diameter_km` (float): Asteroid diameter in kilometers * `impact_speed_kms` (float): Impact speed in kilometers per second * `impact_angle_degrees` (float): Impact angle in degrees This tool will return the estimated impact energy in megatons of TNT, or a helpful error message if any parameter is missing. **Parameter Schema (JSON):** This is how you define the tool’s input parameters in YepCode in the source code editor: ```json { "title": "Calculate asteroid impact energy", "type": "object", "properties": { "impact_speed_kms": { "title": "Asteroid impact speed in kms", "type": "number" }, "diameter_km": { "title": "Asteroid diameter in km", "type": "number" }, "impact_angle_degrees": { "title": "Asteroid impact angle in degrees", "type": "number" } }, "required": [ "impact_speed_kms", "diameter_km", "impact_angle_degrees" ] } ``` #### Testing Your MCP Tool with crewAI Once you’ve configured your MCP server and created your tool, testing it with crewAI is straightforward. * Follow the steps in the [related blog post](https://yepcode.io/blog/crewai-yepcode-mcp-multi-agent-workflows) to set up an example with crewAI. * Your new MCP tool should show up automatically in crewAI’s available tools list. * Agents will use your tool as needed, based on their configuration and tasks. To test it, you just need to run: ![](/_astro/68493e44f9d02793c668ac54_Screenshot-2025-06-11-at-10.28.28.Bkkw2y00_Z2kUTE2.webp) *crewAI run output using your custom MCP tool.* #### **Testing Your MCP Tool in Cursor** Now let’s connect your new MCP tool to an AI platform! Here’s how to configure the YepCode MCP server in [Cursor](https://cursor.so) so your tool is available to LLMs and automations.\*\*Get your YepCode MCP server URL and API token:\*\*‍ * Go to YepCode Cloud > Settings > API credentials to create a new API token. * Your MCP server URL will look like: `https://cloud.yepcode.io/mcp//sse`‍ * For more details, see the [YepCode MCP server repo](https://github.com/yepcode/mcp-server-js). [![Install MCP Server](https://cursor.com/deeplink/mcp-install-light.svg)](cursor://anysphere.cursor-deeplink/mcp/install?name=yepcode\&config=eyJ1cmwiOiJodHRwczovL2Nsb3VkLnllcGNvZGUuaW8vbWNwLzx5b3VyX2FwaV90b2tlbj4vc3NlIn0%3D) > Don’t forget to replace `` with your actual API Token in the MCP server URL. Once connected, you’ll see all the tools you have available! ![](/_astro/684942088be4ece947613b66_Screenshot-2025-06-11-at-10.37.40.CWSgu8mS_Z1inG1b.webp) ### **Best Practices** * Keep tools focused and atomic * Use descriptive names and docs * Handle errors gracefully > **Pro Tip:** Keep your tools small and focused—one tool, one job—for easier maintenance and reuse. ### **Conclusion** MCP custom tools in YepCode let you turn any code into a reusable, cloud-powered action—perfect for LLMs, agents, and automations. > Curious to try this for your own API or use case? [Contact us](https://yepcode.io/contact) — we’d love to hear what you’re building. # Feel the power of n8n and YepCode combined and build amazing workflows > We rely on n8n, one of the most useful no-code tools on the market, to build powerful workflows that require implementing complex logic. Now with n8n Cloud integration and the new Run Code operation. **[n8n](https://n8n.io/)** is a powerful no-code workflow automation tool, but complex workflows can become difficult to maintain. **[YepCode](https://yepcode.io/)** complements n8n perfectly by adding full-code capabilities for complex tasks, data processing, and custom logic. **The combination gives you the best of both worlds:** n8n’s visual workflow builder with YepCode’s coding power, [process versioning](/docs/processes/process-versioning), [audit events](/docs/audit-events), [datastore](/docs/datastore) and much more. > **In short:** n8n handles the visual workflow orchestration while YepCode executes the complex code logic—creating a powerful automation duo. To get started, you’ll need: 1. An [n8n Cloud account](https://n8n.io/get-started/) or self-hosted installation 2. A [YepCode account](https://yepcode.io/) ### Adding a YepCode node to your workflow YepCode is available as a native integration in [n8n Cloud](https://n8n.io/integrations/yepcode/)! We have been early adopters of the community nodes publication feature, and we are excited to see it being used by many users. Previously, tapping into these user-created modules required self-hosting—a hurdle for many without the resources or know-how to manage their own servers. Now, with community nodes integrated directly into n8n Cloud, the barriers to advanced automation are falling away, making it easier than ever to streamline workflows and unlock new possibilities. Here’s how to add it to your workflow: 1. Open your n8n Cloud workspace 2. Create a new workflow or edit an existing one 3. Click the **+** button to add a new node 4. Search for “YepCode” in the node search 5. Select the **YepCode** node 6. Click `Install Node` ## Configuring your YepCode node The YepCode node offers **two powerful operations**: ### 1. Run Code Operation The **Run Code** operation allows you to execute custom JavaScript or Python code directly from your n8n workflow. This is perfect for: * **Quick data transformations** and calculations * **API calls** to services without native n8n nodes * **Complex logic** that would require multiple n8n nodes * **File processing** and data manipulation * **AI-generated code** execution ### 2. Run Process Operation The **Run Process** operation executes existing YepCode processes. This is ideal for: * **Reusable business logic** across multiple workflows * **Version-controlled processes** with proper tagging * **Team collaboration** on complex automation logic * **Long-running tasks** that need monitoring and audit trails ## Setting up YepCode credentials To connect n8n with YepCode, you’ll need to create API credentials: 1. In your YepCode account, go to **Settings > API Keys** 2. Create a new API key 3. In n8n, when configuring the YepCode node, click **“Create New”** under credentials 4. Enter your YepCode API key 5. Test the connection to ensure everything works ![](/_astro/n8n_credentials_01.CIJbnUMp_ZUmeW6.webp) ## Example: Using Run Code The **Run Code** operation can execute any JavaScript or Python code with any package. YepCode automatically installs dependencies as needed. Here’s an example that processes input parameters from previous n8n nodes: ```javascript // Import any npm package - YepCode will install it automatically const { DateTime } = require("luxon"); // Access input parameters from previous n8n nodes const { n8n } = yepcode.context.parameters; const results = []; for (const item of n8n.items) { results.push({ ...item.json, processedAt: DateTime.now().toISO(), }); } // Access n8n metadata - check all available fields at: https://docs.n8n.io/code/builtin/n8n-metadata/ console.log("Environment:", n8n.metadata); console.log("Resume URL:", n8n.metadata["$execution"].resumeUrl); return results; ``` The screenshot below shows the n8n node configuration where you can write your custom code: ![](/_astro/n8n_run_code_config.CR01RTPc_ZrbdGA.webp) ## Example: Using Run Process for complex workflows For more complex scenarios, you can use the **Run Process** operation to execute existing YepCode processes. This is ideal for reusable business logic that you want to version control and maintain separately: 1. Create a process in YepCode with your business logic 2. In n8n, use the **Run Process** operation 3. Select your process and pass the required data 4. Handle the response in subsequent n8n nodes This approach gives you the benefits of YepCode’s process management features like versioning, audit trails, and team collaboration while keeping your n8n workflows clean and focused on orchestration. The screenshot below shows the n8n node configuration where you can select your YepCode process and configure the execution: ![](/_astro/n8n_run_process_config.CHSQm2Ir_1amrnM.webp) ## Best practices * **Use Run Code** for quick, one-off transformations and simple logic * **Use Run Process** for reusable, complex business logic that needs versioning * **Use synchronous execution** when you need the result immediately * **Use asynchronous execution** for long-running tasks that don’t block your workflow * **Test your code** in YepCode’s development environment before using it in n8n That’s it! You’re now ready to combine the visual workflow power of n8n with the coding flexibility of YepCode. Whether you’re using the new **Run Code** operation for quick transformations or the **Run Process** operation for complex business logic, you have the tools to build amazing workflows. Thank you for reading! Happy coding! 🚀 # How to Interact with Any REST API Using YepCode Run and MCP Tools > How to automate real-world workflows by combining YepCode Run, LLM agents (like Claude), and MCP tools. Through the example of interacting with Factorial’s extensive REST API. > LLMs are getting smarter every day — but how do we turn their potential into real, secure, and scalable workflows? In this video, we show how to connect the dots using [**YepCode Run**](https://yepcode.io/run) and [**MCP tools**](https://github.com/yepcode/mcp-server-js/), automating interactions with [**Factorial’s REST API**](https://apidoc.factorialhr.com/docs/getting-started) using nothing more than generated code and a bit of smart orchestration. Whether you’re trying to pull data, trigger operations, or integrate with other systems like Supabase, the combination of **LLMs + YepCode Run + MCP** gives you the power and flexibility to do it all — with minimal human intervention. ## **From Prompt to Code Execution** We start by setting up an intelligent agent (in this case, using **Claude Desktop**) with a prompt that instructs it to solve tasks by generating and executing code through YepCode Run: After adding the initial guidelines, we can start to ask for tasks: ![](/_astro/6841b99a4ed63dbce96c0e34_agent-factorial-api-run-code-mcp-tools-claude-first-prompt._WMi_Q2D_2av5zd.webp) *The agent is set up to solve tasks by generating and executing code with YepCode Run* ## **Exploring APIs with OpenAPI Exploration Tool** To avoid flooding the agent with thousands of tokens from an OpenAPI spec, we’ve built a dedicated **MCP tool**: the **OpenAPI Exploration Tool**. This tool allows the agent to progressively explore an API: * First retrieving available tags and their descriptions. * Then drilling down into specific operations. * Finally, fetching full operation payloads only when needed. ![](/_astro/6841b9e25eb8f396751d6523_agent-factorial-api-run-code-mcp-tools-claude-exploration_tool_screenshoot.BzYl_JAF_1S29Bp.webp) *The OpenAPI Exploration Tool lets the agent explore Factorial’s API step-by-step.* ## **Retrieve Employees information in Factorial** Using the exploration tool, the agent finds the right endpoint and writes code to count employees in Factorial. On its first attempt, the script fails — but the agent detects the issue, rewrites the code, and tries again. ![](/_astro/6841ba0d4771cf42d3f2b22a_agent-factorial-api-run-code-mcp-tools-claude-execution_failed_and_code_is_rewriten.CHAr2REB_Z1NWw0I.webp) *The initial script fails, but the agent debugs and rewrites the code automatically.* After some iterations, the agent retrieves the requested information: ![](/_astro/6841ba36a108f7995f50b5ae_agent-factorial-api-run-code-mcp-tools-claude-employee_count_success.B3BYZL-q_10Kqef.webp) *The agent retrieves and logs the number of employees* ## **Creating Time-Off Requests Automatically** Next, we ask the agent to create a **leave request for an employee** named Elizabeth during the last week of June. The agent: * Looks up the relevant endpoints. * Retrieves the employee ID using her email. * Checks available leave types. * Submits the request. ![](/_astro/6841ba5cda850b97ebefdc92_agent-factorial-api-run-code-mcp-tools-claude-second_prompt_asking_for_leaves_creation.CKE-yL6G_ZPdzNv.webp) *The second prompt asks the agent to create a leave request for a specific employee.* ## **This Isn’t Just Another REST API Wrapper** Although this flow might initially seem like just a smart wrapper over a REST API, it’s much more than that. What we’re building here is a flexible and extensible system where the agent isn’t limited to a predefined set of endpoints or rigid logic. Instead, it understands the context, explores APIs dynamically, and generates custom code to solve tasks — even combining multiple services or adapting to different environments as needed. To take it a step further, we challenge the agent to store the employee data in **Supabase**. It attempts to create the table programmatically, fails, asks us for help — and after we manually create the table, it stores the data successfully. ![](/_astro/6841bae427fd9e4de386cf40_agent-factorial-api-run-code-mcp-tools-claude-supabase_prompt.DroSdxAs_Z1wk1gv.webp) *The agent is prompted to store employee data in Supabase* ## **A Glimpse into the Future of Workflow Automation** It might feel like using a sledgehammer to crack a nut — but with LLMs getting better and better at generating high-quality code, this approach makes a lot of sense. It’s not just about automating a simple task, but about building an environment where agents can adapt, iterate, and solve complex workflows autonomously. We’re laying the foundation for a new way of interacting with APIs and systems: smarter, more flexible, and with almost limitless potential. > Curious to try this for your own API or use case? [Contact us](https://yepcode.io/contact) — we’d love to hear what you’re building. # Make.com Meets Code: Introducing the YepCode Run Connector for Make > Discover how the YepCode Run connector for Make.com lets you execute custom serverless functions, use AI-generated code, and extend your no-code workflows with full coding power — securely and without infrastructure headaches. 🤝 *NoCode and YepCode?* Turns out they can play nicely together — and when things get complex, they make a *great* team. We’re thrilled to announce that **YepCode is now available as an official connector in** [**Make**](https://www.make.com) (formerly Integromat)! 🎉 This integration brings the full power of **custom serverless code execution** right into your no-code scenarios — unlocking a whole new level of flexibility for creators, developers, and automation pros. ![](/_astro/6846d9078b75937a29455a70_1.j1a3-mCN_2kiSL7.webp) ## **🚀 Why We Built It** At YepCode, we’re all about connecting services, APIs, and databases through code — quickly, securely, and without managing infrastructure. But we also know that **no-code platforms like Make are fantastic for building fast, visual automations**. Still, there’s a limit to what can be done without code. And that’s exactly where YepCode comes in. When your Make scenario needs to: * Call a less-common API that doesn’t have a native Make module * Transform complex data structures * Or let an AI agent generate and execute custom logic… **YepCode is now just a connector away.** ## **✨ What You Can Do** The new **YepCode Run** connector enables you to: ✅ **Execute any custom serverless function directly from Make**, by mapping your YepCode function inputs right inside the scenario ✅ **Use LLM-generated or prebuilt code** to connect to services, APIs, or databases — including **any PyPI or NPM package** (we handle all the dependencies) ✅ **Supercharge your no-code flows** with the flexibility of code — without setting up servers or managing deployments ![](/_astro/6846d97ec83d47b3f75bc4c4_2.H4QrYjn0_1yAcnH.webp) ## **🤖 Make AI Agents + YepCode = Endless Possibilities** Our new connector is a perfect companion for Make’s powerful AI Agents. Let’s say your agent is smart enough to generate the right code to solve a task — but has no way to run it. That’s where YepCode comes in. ⚡ By plugging YepCode into the flow, you give your agents a secure, scalable, and flexible execution environment. It’s not just about suggesting a script — it’s about getting the job done. This approach it’s perfect to be used as **fallback tool** when your current scenarios doesn’t fit. ![](/_astro/6846d964dc9fc60498498824_3.BmCaOu30_1p2Pnz.webp) ## **🧪 Want to Try It? Let’s Build Together** 👉 **Give it a spin** inside Make — just search for “YepCode Run” in the scenario builder. Got a complex use case or idea you’d love to prototype? We’re happy to **collaborate on automation POCs (proofs of concept)** — just tell us what you have in mind! ## **🔗 Ready to Connect?** You can explore more about YepCode at [yepcode.io](https://www.yepcode.io), or jump straight into [Make.com](https://www.make.com) to start using the connector. Let’s see what happens when no-code and full-code join forces. Because automation should have **no limits**. # Automating Outbound Sales Workflows with Latitude AI Agents, and YepCode MCP tools > Discover how to streamline your outbound sales processes using MCP, Latitude, and YepCode. Automate lead generation, outreach, and follow-ups with AI-powered tools and seamless workflow integrations. #### **🚀 Automating Outbound Sales Workflows with MCP, Latitude, and YepCode** Last week, we published a video showcasing our new [**MCP Server**](https://github.com/yepcode/mcp-server-js) — a powerful tool that makes it easy to securely run AI-generated code and expose tools created in YepCode as **MCP tools**. This lets any LLM interact with these tools safely, in a scalable, sandboxed environment. In the demo, we walked through how you can quickly build a tool using a simple JavaScript or Python snippet in YepCode, and expose it as an MCP tool. We integrated it with [**TheirStack**](https://theirstack.com/), a platform that helps detect job openings as hiring signals — so, for example, if a company is hiring for AI-related positions, it might be a perfect moment to pitch them a relevant solution. #### **🛠️ From Idea to Full Automated Workflow** After sharing that demo, one of TheirStack’s founders suggested a more complete workflow idea: • **Find job signals** using TheirStack • **Visit the company website** • **Identify contacts** via Apollo.io • **Draft a cold email** • **Log everything** to be used by the company sales team We loved the idea — and built it! To make this work, we used [**Latitude.so**](https://latitude.so/), a platform that helps you manage and optimize AI prompts, and create smart AI agents. Latitude allows you to connect external tools, so we connected our the **YepCode MCP server** with these tools: • A **TheirStack tool** to get job postings • An **Apollo tool** to find contacts • A **Linear tool** to log information You may download the tools source code [here](https://drive.google.com/file/d/15lgTgF9LRQu0iXOfCIru1kdVvbuiN21n/view?usp=sharing) (and [import them](/docs/processes/import-export) in your YepCode account). We designed a workflow prompt in Latitude telling the agent to: 1\. Search for job signals on TheirStack 2\. Use Apollo.io to find key contacts 3\. Visit the company website 4\. Draft a personalized cold email 5\. Create a Linear issue summarizing all the details This is the full agent prompt: The workflow is fully automated — you just fill in parameters like job keywords, employee count, and target roles. The agent fetches job postings, finds people, writes the email, and logs everything in Linear. You could even extend it to send emails directly using our email sender tool. #### **🎥 See It In Action** You can watch the full video [here](https://www.youtube.com/watch?v=QdOAEl3V6Kk) to see this workflow running live — how Latitude coordinates the process, how each MCP tool is executed via YepCode, and how everything gets neatly organized in Linear. It’s a perfect example of how you can automate outbound sales workflows combining AI agents, low-code tools, and secure serverless environments. #### **🏁 Want to build your own MCP tools and automate your sales process?** Create your [YepCode.io](https://cloud.yepcode.io) account and get started today! # Building an AI Agent with YepCode Run for Dynamic Code Execution > Discover how to build AI agents that generate and execute code securely with YepCode Run—a serverless runtime for safe, efficient execution in isolated sandboxes. 🚀 #### Why YepCode Run? AI agents capable of writing and executing code autonomously are becoming increasingly powerful. However, running **AI-generated code** securely and efficiently remains a challenge. That’s where YepCode Run comes in—a serverless runtime and SDK for executing code in secure sandboxes. In this post, we’ll show how to use YepCode Run to build an AI agent that solves tasks by generating and running code dynamically. ✅ The execution happens in a secure, sandboxed environment. ✅ The infrastructure scales automatically as needed. ✅ You don’t have to worry about dependency management. YepCode Run provides all of this out of the box so you can focus on your code rather than infrastructure concerns. #### How can I use it? We provide both [JavaScript](https://www.npmjs.com/package/@yepcode/run) and [Python](https://pypi.org/project/yepcode-run/) packages, so you may easily integrate YepCode Run in you projects. We have also created a [playground page](https://yepcode.io/run) to try any piece of code. #### Building an AI Agent That Solves Tasks with Generated Code Let’s implement an AI-powered agent that takes a task description, generates an executable script, runs it securely using YepCode Run, and iterates if needed. Here’s how it works: ##### The Prompt This prompt guides the AI to generate clean, executable JavaScript or Python code that solves a task while sticking to YepCode’s structural standards and package management best practices. 🚀 Failed iterations prompt: ##### Show me the code! We tackle tasks by generating and running code. As LLM we have gone with Anthropic Claude API (Claude 3.5 Sonnet). Our approach is iterative—learning from errors, logs, and past failures to refine each attempt until we get it right. A standout feature? Seamless handling of environment variables like API keys and passwords. We don’t expose their values to the LLM—YepCode securely manages them at execution time—but we ensure they’re referenced in the prompt. Our workflow is straightforward: 1\. Read the task and environment variables from files. 2\. Prompt the LLM to generate code. 3\. Execute the code with YepCode. 4\. If it works—great! If not, we iterate until it does (or hit the retry limit). Smart, adaptive, and efficient—just the way automation should be. 🚀 This is the JavaScript full code (python version below): If you prefer the python version: The two environment variables needed to run this are: #### What kind of tasks can be solved with this? As the source code may include any npm or pypi dependency, and you may provide environment variables to connect to private services, the options are endless. For example this task needs to connect to some remote server and then save information in one MySQL server, and the agent has been fully capable to solve it in two iterations: #### 🏁 Conclusion With YepCode Run, you can create an AI-driven agent that writes, executes, and refines its own code in a **secure, serverless environment**. Whether you’re exploring new ideas, testing AI-generated scripts, or integrating automation into your workflows, YepCode Run has you covered. **Try YepCode Run today and supercharge your AI-powered coding workflows!** 🚀 # Announcing StoreFlow, serverless functions across your cloud storage > We’ve brought YepCode’s power to cloud storage systems, so you can forget about connectivity headaches, file scanning and monitoring, or scalability challenges—and focus entirely on unlocking the value of your data with maximum flexibility. 🚀 Getting value from your cloud storage data shouldn’t be a hassle! Right now, teams are building whole projects to keep track of files, running repetitive processes, and struggling to automate workflows across Amazon Web Services (AWS) S3, Google Cloud Storage, and Azure Cloud Blob. **🔍 The challenge?** Most storage solutions focus on storing data and provide simple ETL solutions—not what happens next. Businesses need an easier way to find, process, and automate actions on their files without complex engineering work. **✨ Meet YepCode StoreFlow – your cloud storage automation powerhouse.** With YepCode StoreFlow, you can: ✅ Unify your storage across cloud providers in one powerful UI. ✅ Find files fast with advanced search filters. ✅ Build & run serverless functions on files—no infrastructure headaches. ✅ Trigger automations when new files arrive or change. \*\*💡 How does it work?\*\*‍ 1️⃣ Connect Your Cloud Accounts: Securely link your AWS, Google Cloud, and Azure accounts, enabling monitoring of your storage buckets. 2️⃣ Create and Configure Functions: Choose from our catalog or develop custom functions in JavaScript or Python using any external package to perform specific operations on your files. 3️⃣ Search and Select Files: Utilize advanced filters to locate and select files across your connected storage systems. 4️⃣ Set Up Smart Listeners: Configure listeners to automatically handle tasks for new uploads or specific conditions, reducing manual effort. 5️⃣ Monitor Executions: Track the status of your functions and review logs for each file processed. By following these steps, YepCode StoreFlow simplifies your cloud storage workflow, allowing you to focus on what truly matters—your core business operations. Check our [full demo video](https://youtu.be/lBX3ZwDGzxw) (spanish). # Announcing the YepCode Copy Team GitHub Action! > This action ensures seamless synchronization of processes and modules between YepCode workspaces, perfect for promoting your staging environment to production ### What are GitHub Actions? GitHub Actions is a powerful automation platform that allows you to create custom workflows directly in your GitHub repositories. By defining workflows in YAML files, you can automate tasks like building, testing, and deploying code. GitHub Actions supports a wide range of triggers, such as code pushes, pull requests, and more, making it a versatile tool for DevOps and CI/CD pipelines. ### Introducing the YepCode Copy Team GitHub Action We are excited to introduce our new YepCode Copy Team GitHub Action! This action is designed to ensure seamless synchronization of processes and modules between YepCode workspaces. It’s perfect for promoting your staging environment to production without any hassle. It leverages the [YepCode CLI](/docs/cli/) to remotely manage changes in your YepCode account and can also be used to synchronize processes and modules between installations in different environments, such as on-premise installations. #### Key Features: * **Seamless Synchronization**: Easily copy resources from one YepCode team to another. * **Environment Promotion**: Ideal for promoting changes from staging to production environments. * **Efficiency and Automation**: Streamline your workflow and reduce manual intervention. 🔗 [Check out the YepCode Copy Team GitHub Action](https://github.com/marketplace/actions/yepcode-copy-team-github-action) ### How to Use the YepCode Copy Team GitHub Action Using this GitHub Action is straightforward. Simply add it to your workflow file in your GitHub repository and configure the necessary parameters. Here’s a basic example to get you started: ### Extending to Other Pipelines You can easily adapt this action as a template to create similar automation pipelines for other platforms, such as Bitbucket Pipelines, and as we always say, don’t hesitate to [reach us](https://yepcode.io/contact) if you need some kind of help with this or other YepCode related tasks! ‍ # YepCode Achieves SOC2 Type I Security Certification! > We are thrilled to announce that YepCode has achieved SOC2 Type I security certification. Combined with our GDPR compliance, this milestone underscores our commitment to the highest standards of data security and protection. We are thrilled to announce that YepCode has achieved the SOC2 Type I security certification! 🎉 This milestone is a testament to our unwavering commitment to the highest standards of security and data protection for our customers. #### What is SOC2 Type I Certification? SOC2 (System and Organization Controls 2) is an auditing procedure that ensures service providers manage customer data with the highest standards of security, availability, processing integrity, confidentiality, and privacy. The Type I certification evaluates the effectiveness of our systems and controls at a specific point in time. #### Why This Matters In today’s digital landscape, security is more critical than ever. Achieving SOC2 Type I certification demonstrates that YepCode has established rigorous policies, procedures, and practices to safeguard our customers’ data. This certification provides our clients with the assurance that their data is secure with us, enabling them to focus on what they do best—innovating and growing their businesses. #### Our Commitment to Security At YepCode, security is at the core of everything we do. From our robust microservices architecture to our comprehensive CI/CD practices, we ensure that every layer of our platform adheres to the highest security standards. Here are a few ways we prioritize security: * **Data Encryption**: We use advanced encryption methods to protect data at rest and in transit. * **Access Controls**: We implement strict access controls and authentication mechanisms to ensure that only authorized personnel can access sensitive information. * **Regular Audits**: We conduct regular security audits and assessments to identify and mitigate potential vulnerabilities. If you have any questions about our SOC 2 Type II compliance or any other aspect of our security and data protection practices, you can [contact us](https://yepcode.io/contact) directly. #### GDPR Compliance In addition to our SOC2 Type I certification, we are also proud to announce that YepCode is fully GDPR compliant. This compliance ensures that we meet the stringent data protection and privacy regulations set forth by the European Union, further reinforcing our commitment to protecting customer data. #### Our Certification Journey To support our certification process, we partnered with [Vanta](https://www.vanta.com/), a leading platform that streamlines SOC2 compliance. Vanta provided us with the tools and guidance needed to ensure our systems met the rigorous SOC2 standards. The audit was conducted by [Prescient Assurance](https://www.prescientassurance.com/), a trusted name in security and compliance assessments. Their thorough evaluation confirmed that YepCode adheres to the highest security protocols. #### What’s Next? Achieving SOC2 Type I certification is just the beginning. We are committed to continuous improvement and will soon be working towards SOC2 Type II certification, which evaluates the effectiveness of our security practices over a period of time. #### Thank You We want to extend our heartfelt thanks to our dedicated team and loyal customers. This achievement would not have been possible without your trust and support. As we continue to innovate and expand our platform, rest assured that security will always remain a top priority at YepCode. Our main target market is Enterprise companies, where certifications like SOC2 and GDPR compliance are essential. This milestone underscores our dedication to meeting the highest security standards demanded by our enterprise clients. Stay tuned for more updates and exciting developments. Here’s to building a more secure and efficient future together! Thank you for being a part of our journey. # Manage Multiple Teams Seamlessly with the Enhanced YepCode CLI > Discover how the YepCode CLI streamlines multi-team management, enhancing collaboration and security in software development workflows. Hello Developers! At YepCode, we’re always looking for ways to make your life easier, and we’re excited to announce a powerful upgrade to our YepCode CLI (Command Line Interface). This new update takes the capabilities of our CLI a step further, allowing you to **manage multiple YepCode teams for staging, development or production environments** with incredible ease. Let’s see how this enhancement can **streamline your workflow and increase collaboration across your projects**. ## Unleash the Power of the YepCode CLI In previous video tutorials we have shown you the capabilities of the YepCode CLI and how it can revolutionize your development process. Imagine being able to **design and execute processes locally** and then, with just a few clicks, upload them to the YepCode cloud for **scheduling, webhook triggering, and thorough auditing**. All while staying in your familiar local environment. The YepCode CLI is an NPM package that’s easy to install and use. While you’ll need a YepCode account to unlock its full potential, the CLI is openly available, and you can find the full command syntax on the NPM website. ## Multi-Team Management: Collaboration Made Simple Here’s where things get exciting: **the enhanced YepCode CLI now allows you to manage multiple YepCode teams**. Whether you’re working on a development team, a staging team, or a production team with restricted access, the CLI allows you to seamlessly **synchronize your work across these different teams**. Our in-depth video tutorial shows you how to clone teams, manage processes and their versions locally, and easily push changes to the cloud. **We also show you how to handle conflicts and maintain version control** to keep your development process smooth and organized. ## Supercharge Your Workflow with CI/CD Integration But that’s not all , the **you can integrate YepCode CLI with popular CI/CD pipelines like GitHub Actions or Bitbucket Pipelines,** allowing you to automate deployment between your YepCode teams and ensure a smooth, efficient development process. ## Security, Collaboration, and Efficiency: The Winning Trio YepCode CLI empowers you on multiple fronts. Improved security is one of its key benefits, allowing you to **restrict access to production environments while allowing free development in staging or development teams**. Collaboration is also an essential asset, encouraging seamless teamwork across different teams. And finally, efficiency takes center stage with optimized workflows: a developer’s dream! So if you’re ready to take your development workflow to the next level, be sure to check out our latest video-tutorial where we reveal the main uses of multi-team management in our YepCode CLI. Happy coding! [Enhanced YepCode CLI: Streamline Your Workflow with Multi-Team Management](https://www.youtube.com/embed/sguJ8IzR1EI) # Unlocking the Power of YepCode Landings: Create Dynamic Web Pages in Minutes! > Discover how effortlessly you can create fully completed HTML web pages in minutes, revolutionizing your workflow and boosting your online presence. Hello friends, web creators and code lovers! Today, we’re embarking on an exciting trip into the world of YepCode: YepCode Landings. Have you ever had to deal with the hassle of having to create and manage unique landing pages for each campaign? Get ready to se­e something really ne­w in web building! You can simplify the landing creation with customisable HTML layouts that will allow you to generate countless landings effortlessly. ## Making Dynamic Templates with YepCode Landings Imagine this: you start with a blank page, and quickly, you’ve made a template like our “Hello World Template,” with parameters using the easy ‘Mustache’ syntax. It’s like magic, but better, it’s YepCode Landings. ## Deploying Fully Completed Pages in No Time Once your template is ready, it’s time to bring it alive. Just pick your template, add a URL path, give it a catchy name and fill in those parameters. Click a few buttons, and voila! Your web page is ready to rock and roll. ## Scaling Complexity? No Problem! But wait, there’s more! YepCode Landings isn’t just about simple tasks. Jump into the deep end with complex layouts, images, styles—you name it. YepCode Landings can handle it all, making even the trickiest projects a walk in the park. ## SEO Superpowers Unleashed Now, let’s talk about SEO. YepCode Landings doesn’t just make good-looking pages, it boosts your online presence. Imagine making thousands of landing pages using a CSV file, each one tailored to perfection. Yep, that’s the power of YepCode. ## Flexibility? You Bet! Got a change of heart? No worries. Whether you’re adding a YepCode form or adjusting layout details, YepCode Landings offer flexibility. It’s like having your own personal web development playground. ## Efficiency and Speed? Absolutely! And last but not least, speed and efficiency. With YepCode Landings, you can kiss goodbye to those long, tedious hours of manual labor. Say hello to quick creation and smooth deployment, all at the click of a button. ## Ready to Rock? Let’s Go! So, are you ready to revolutionize your web development game? Join us on this epic journey into the world of YepCode Landings. Watch our video tutorial below to discover just how easy it is to create dynamic web pages in minutes. Happy coding, everyone! [Speed up your Web Development with our Automatic Landing Page Generator.](https://www.youtube.com/embed/IBlviq_oxgc) # Unveiling the Power of Automatic Image Descriptions with YepCode and OpenAI > We dive into the capabilities of YepCode combined with Open-AI, demonstrating how it simplifies the process of creating accessible and SEO-friendly image descriptions. In the realm of digital communication, images serve as powerful tools for conveying information, evoking emotions and capturing attention. However, **the significance of image descriptions cannot be overstated**. They play a crucial role in accessibility, SEO and overall user engagement, but sometimes we do not have enough time to write the most suitable words to describe an image correctly, neither the skills. In this article, we’ll explore **how to effortlessly automate the process of generating image descriptions**. Powered by **OpenAI**, this powerful alliance promises **a seamless experience in image-to-text conversion**. ## Demystifying AI Image Descriptions Generation: YepCode’s Approach We use the power of AI to analyze and interpret visual content, **extracting meaningful information and translating it into natural language descriptions**. This image description generation process involves several key steps: ### Creating YepCode Forms for Image Descriptions YepCode streamlines the process by [allowing users to define input parameters using a JSON schema or a user-friendly builder](/blog/introducing-yepcode-forms-easy-embedding-process-executions). In this instance, our form prompts users with a single question—what information do you want about this image? Additionally, users can upload an image file in BASE64 format. ### Rendering the Form Upon rendering the form, YepCode extracts the parameters from its context and parses the image in BASE64 format. This prepares the image for integration with the OpenAI API, with the additional requirement of providing the API KEY. ### Integration with OpenAI API The magic happens when YepCode seamlessly integrates with the OpenAI API. By providing the API key, users unlock the potential of AI-powered image understanding. **AI algorithm analyzes the uploaded image, identifying objects, scenes and activities depicted within the visual content**. ![Marcos Muíño doing rappel in the AR World Championship South Africa 2023](/_astro/655f08d9739afdd0944cb227_Marcos-Muino-in-AR-World-Championship-South-Africa-2023.0B9fnYnr_2c2dwL.webp) Marcos, YepCode founder in the AR World Championship 2023 ### Generating Descriptions with Confidence OpenAI’s prowess shines through as it **analyzes images and generates human-readable phrases** with confidence scores. The algorithm produces multiple descriptions based on various visual features, ensuring a comprehensive understanding: * **Semantic Understanding:** Beyond object detection, Open AI delves into the deeper meaning of the image, comprehending the relationships between objects, the emotions conveyed, and the overall context of the scene. * **Natural Language Generation:** Open AI transforms the extracted semantic understanding into natural language, crafting a descriptive caption that accurately conveys the essence of the image. These descriptions are then ordered from highest to lowest confidence, providing users with valuable insights. ![](/_astro/655df7900e03f6efd6791331_Image-Description-generated-for-the-image-of-Marcos-in-AR-World-Championship.CAn06wt9_2vzA9J.webp) Example of description generated through AI ### Embedding the Form Anywhere We go beyond the conventional by enabling users to **embed image description forms seamlessly**. Whether it’s a WordPress site, a Webflow page, or any platform that supports HTML code, **YepCode’s forms SDK ensures that the user-friendly input parameters form becomes an integral part of the web page**. ![YepCode form embedded for Generating Image Description thanks to OpenAI](/_astro/655df6eb81555af574e84404_Image-Description-Generation-YepCode-Form.KPhF1aMZ_Z1BfQtx.webp) YepCode form to generate automatic Image descriptions ## Benefits of AI Image Description Generation The integration of AI image description generation into content creation and management offers a multitude of benefits for individuals, businesses, and organizations: * **Enhanced** **Accessibility**: Automating AI-generated image descriptions, ensures that visually impaired individuals or those using screen readers can fully access and understand the content of images. * **Improved SEO**: YepCode-generated image descriptions provide search engines with valuable context, improving the searchability of your images and boosting your website’s overall SEO performance. * **Engaging Visual Content:** Descriptive image captions add a captivating layer of narrative to images, making them more engaging for all audiences. ## **Real-World Applications of AI Image Description Generation** Image description technology using AI goes far beyond traditional websites and online content and has a wide scope of application in a variety of industries and scenarios: * **E-commerce:** AI image descriptions can provide detailed product descriptions for visually impaired shoppers, enhancing their shopping experience and improving accessibility. * **Social Media:** AI-generated captions can make social media posts more accessible and engaging for a wider audience. * **Education:** AI-powered image description tools can aid in creating inclusive educational materials for students with visual impairments, providing them with equal access to visual learning aids. ## **A Real-world Use Case** To illustrate the whole process, we have recorded a **video tutorial explaining how to create a form to upload a photo and automatically get an AI-generated description**, step by step.We submit an image of the last world championship of Adventure Races. OpenAI processes the image in seconds and provides insightful results. The simplicity, speed and accuracy of this integration not only enhance accessibility but also redefine the way we interact with visual content. Enjoy the video and happy coding! [Describe image using YepCode and OpenAI API](https://www.youtube.com/embed/OEQ2ok2z5tA) # Balaena Toolkit > Implement YepCode processes to integrate the leads received from their webpage into their HubSpot CRM. ## Sphere Booking management ## How did they use YepCode Implement YepCode processes to integrate the leads received from their webpage into their HubSpot CRM. ## Results They saved significant time, avoiding doing this task manually. # Docuten > Extend their core product, adding additional electronic invoice formats without touching their core. ## Sphere E-sign provider ## How did they use YepCode Extend their core product, adding additional electronic invoice formats without touching their core. ## Results In just one day, a request from their clients to add a new electronic invoice format was implemented. That leads to close new deals with revenue increasingly. # Nivimu > Add a bunch of integrations with other HR platforms. ## Sphere Human resources SaaS ## How did they use YepCode Add a bunch of integrations with other HR platforms. ## Results Significantly improved their client’s engagement. # One of the biggest retail companies > Keep sync TB of daily sales information between their distributed databases. ## Sphere Retail ## How did they use YepCode Keep sync TB of daily sales information between their distributed databases. ## Results Significant improve of effectiveness. All their information is fully synced and it is pretty easy to change these ETL processes to fit new business every-day needs. # Tracktherace > Implement YepCode processes to support new tracking devices protocols and without changing their platform. ## Sphere Sports GPS tracking ## How did they use YepCode Implement YepCode processes to support new tracking devices protocols and without changing their platform. ## Results They were able to close more deals with events using the new supported devices, and add more devices is a very fast task. # Unchained Music > Automate leads form submissions management in their internal documents. ## Sphere Music distribution, Royalties Management ## How did they use YepCode Automate leads form submissions management in their internal documents. ## Results Validate an MVP getting early adopters for their new Royalties Management platform in weeks, not months. # Introducing YepCode Forms: Easy embedding of process executions > We have created a complete video-tutorial, where we'll show you how to configure YepCode Forms from start to finish and we'll explore all the amazing possibilities that come with this powerful new tool. For those of you who already know YepCode there is little to say, but for those who don’t, we invite you to discover this incredible automation platform that can revolutionize the way you work. And that’s not all: YepCode has just launched a [**new feature called YepCode Forms**](/docs/forms), which we are happy to share with you. In this blog post, we’ll explore **how YepCode Forms work** and how they can help you **create custom forms that trigger YepCode process executions**. So, grab a drink, settle in and get ready to discover how YepCode Forms can take your workflow to the next level! ![](/_astro/645a184240a6b91aba56ea67_form-preview.Cv6cw8dl_Z6Uz3e.webp) Getting started with YepCode forms is super easy. To begin, head over to the **YepCode documentation page, where you’ll find detailed information** on how these forms work and how to configure them. With YepCode Forms, you can easily trigger any type of YepCode process by asking users for input parameters. And the best part? You can **embed these forms in any external website**. In the following **video, we are going to see an example of creating a form** to allow users to register for a webinar. To do this, we need to create a new YepCode process, configure the parameters and enable the form. We then copy the code and embed it in our website using an embed element. Once the form is rendered, we can customize it to suit our needs. [Empower your web pages with YepCode Forms | Full configuration tutorial](https://www.youtube.com/embed/ZA6XIkKMKXo) With YepCode Forms, customizing your form has never been easier! You have full control to modify the title, input fields, and attributes to fit your specific needs. Plus, once a user submits the form, you can trigger process execution and collect input parameters to send personalized messages back to the user. But that’s not all. Here is a **list of some amazing things you can get with our forms**: * Integrations with (ie: [HubSpot](https://www.hubspot.com/)) to create new users and send emails or [Slack](https://slack.com/) messages * Multiple configuration options, including **embedding with function or div code**, using a **React component** and customizing form behavior with **callback functions** and **error handling** * Default behaviors like **redirecting to a URL** or executing a **JavaScript callback** * **Style customization options** such as setting default parameters, customizing with **CSS variables** and changing the text on the submit button to match branding What’s more. You can go further and create some seriously awesome forms, even if they’re complex ones with requests for **attributes or file uploads**. And the best part? It is easy to embed the whole process right into any web page you want and create custom forms that trigger those executions. If you’re looking to **streamline your business processes**, you have to check out YepCode Forms. Thanks for reading and happy coding! # YepCode Now Supports Python: Build Integrations and Automations Easily > This expansion opens up new opportunities for developers to build integrations and automate processes in a serverless environment using Python, one of the most popular programming languages. # **YepCode now supports Python - Streamline your Integrations and Automations** After a long time listening to our users’ requests, we are finally super excited to announce a new milestone in our roadmap. Our development team has been working hard to make it possible and finally, this is it, YepCode now supports Python! Our all-in-one platform allows development teams to create integrations and connect services and APIs in an agile way within a serverless environment. And now, we’re going one step further by extending our technical capabilities to include a new programming language. With all that this entails. So why is this a big deal? Well, implementing Python means that we can further expand our business and help even more developers meet their needs. And let’s face it, Python is one of the most widely used programming languages in the world, so it just makes sense for us to support it. ## **Why Python is a Great Language for Integrations and Automation? There are good reasons** For those of you who are not familiar with Python, let us fill you in! Python is a high-level programming language that is easy to learn and use. It is ideal for beginners and experts alike, and is used in a wide variety of fields, including web development, scientific computing, data analysis, and machine learning. Python’s simplicity and readability make it an excellent language for building integrations and automations. Its extensive libraries and frameworks also make it easy to connect to many services and APIs. Additionally, Python’s cross-platform compatibility and dynamic typing make it a versatile language to be used for countless applications. One of the best things about Python is its flexibility. You can use it for everything from simple scripts to complex applications, and it has a huge library of pre-built modules and tools to help you get your work done. And because it’s so popular, there are tons of resources and communities out there to help you learn and get support. Some of its key features are: * Easy to learn and read code * Extensive libraries and frameworks for various applications, including machine learning and data analysis * Interpreted language, meaning no compilation is required * Cross-platform compatibility * Dynamically typed, meaning variables do not need to be declared before use ## **What technical aspects have we developed to include Python in YepCode?** We know that Python was a highly requested feature, so our team of developers is working extensively tirelessly to adapt our integrations and recipes to Python, as well as include Python snippets in our documentation, so you have everything you need to get started. In our editor, you can see and prove the code to implement your processes. Depending on the language you want to use, the script will be executed in a different engine. In the case of using Python, we use the [**Python v3 engine**](https://www.python.org/)**,** so you can almost every function that Python supports. YepCode allows using external services through integrations This makes it possible to read and publish information from and to databases, APIs, SaaS, Storage Systems, etc. Python integrations rely on open-source packages. We use [**pip**](https://pypi.org/), the package installer for Python. We have also included some well-known libraries that will help you to write your scripts in the most agile way in both JavaScript and Python languages. In addition to these integration libraries, we also allow using all [**Python built-in modules**](https://docs.python.org/3/py-modindex.html). ### **How do I get started with Python in YepCode?** To get started with Python in YepCode, simply create a new recipe or integration and select Python as the language. You can then use our built-in Python snippets or add your code to customize your integration. And if you’re new to Python, don’t worry - our documentation includes plenty of resources to help you get started. ### **What’s next on our roadmap?** We are releasing new Python features every week. So we are working now to implement new Python Modules that will allow you to define an isolated set of Python functions to be reused from any of your processes. These modules can help you share functions between processes to solve some business logic problem, encapsulate access to a service, or any other purpose where splitting the code into modules makes sense. Whether you’re looking to streamline your integrations, automate your workflows, or perform complex ETL processes, YepCode with Python has got you covered. So why wait? Try it for yourself and see how YepCode can simplify your development process today. Thanks for reading, and as always, happy coding! # Extending Your SaaS Capabilities with YepCode Forms: Tinybird Example > Learn how to embed input forms into your applications using YepCode Forms. With its SDK in JavaScript, YepCode Forms can extend the functionalities of other SaaS products. In this post, we’ll be discussing one of the latest and most interesting features of YepCode - YepCode Forms. As you know, YepCode is a platform that allows users to perform **integrations and automations between an infinite number of services** in a simple way. But what sets YepCode apart is its ability to [**extend the functionalities of other SaaS products**](https://yepcode.io/blog/docuten-extended-saas-features-using-yepcode), which is where the YepCode Forms feature comes in handy. [**YepCode Forms**](/docs/forms/) is a mechanism that allows the **input form of a YepCode process to be embedded in any type of application or webpage**. By using the YepCode SDK published in JavaScript, you can embed ‘divs’ with your team’s name, process name, callback functions, and error handling to enable the use of YepCode Forms in your application. ![](/_astro/64006aac1247f24830069149_YepCode-forms-in-Tinybird---IM1.B8FaSC6z_Z1y161m.webp) Once embedded, you can trigger an execution of the YepCode process that includes all the code you need to go to a database, retrieve information, perform REST or GraphQL invocations, or any other action you’re interested in. ### **YepCode forms in Tinybird** We are going to explore now a specific case of using YepCode Forms with [**Tinybird**](https://www.tinybird.co/), a popular serverless database platform. We will see how a new information ingest system can be incorporated into Tinybird **without modifying the core of its product**. On the **home page** of the Tinybird dashboard, **we have embedded a YepCode form** that allows users to choose a type of database, such as MySQL, PostgreSQL, or ClickHouse. The form asks users for a host, port, username, and password. Users must indicate which query they want to execute against this database (in this example, MySQL) to export the results and take them to Tinybird. ![](/_astro/64006b4d47d0152b21bc928b_YepCode-forms-in-Tinybird---IM2.BcbwE8Zm_1QO55l.webp) For instance, if you select the ‘flight’ table from ‘airportDB’, you can put a select query and give the name to the DataSource in Tinybird. ![](/_astro/64006b7a10a9c91c5a72f235_YepCode-forms-in-Tinybird---IM3.DErwOW07_Z2nvWsM.webp) When **submitted, this triggers the execution of the YepCode process**, which imports the data **very fast** thanks to the fact that Tinybird imports the data very quickly, and the [**YepCode process uses a streaming approach**](https://yepcode.io/blog/nodejs-stream-system-to-move-data-and-save-memory-consumption), without loading the data in memory. This means that **the import process is very agile** and can handle large amounts of data seamlessly. ![](/_astro/64006b98dcf3483e760437a5_YepCode-forms-in-Tinybird---IM4.DeZegzBC_Z2u13Uu.webp) Overall, YepCode Forms is a powerful feature that can help users extend the functionalities of other SaaS products. With its ease of use and flexibility, it’s no wonder why **YepCode Forms is quickly becoming a favorite among developers** and users alike. In the next **video**, you can **see the full-detailed process** and see how YepCode Forms can help you achieve your integration and automation goals. Enjoy it and… Happy coding! 🧑‍💻 # Support visitor comments in Webflow blog using YepCode forms > We will show you how to support visitor comments on your Webflow blog using YepCode forms. Increase your engagement and build a community around your content, allowing visitors to leave comments. In this article, we are going to show step by step how to add comments support to one Webflow blog. One [YepCode form](/docs/forms) will be embedded into the blog post page, asking for the visitor name and message. This form submit will start one [YepCode process](/docs/processes) execution that will create a new Webflow CMS entry to store that information. This CMS collection will be rendered in each blog post, showing the visitor’s comments. ## Steps summary This will be the sections that we’ll cover in the article: * Clone a Webflow template to create a brand-new blog * Add a new CMS collection to store the blog post comments * Change the blog post page template to render these comments * Build a new YepCode process to create these CMS entries * Enable YepCode forms for this process * Embed the form into the blog post page template * It’s done! ## Clone a Webflow template to create a brand new blog To build the sample from scratch, we are cloning [a FREE Webflow template](https://webflow.com/templates/html/moon-blog-website-template). ![](/_astro/63d197ec794522f426123310_Moon-Blog-HTML5-Responsive-Website-Template.DUpbic9K_Z1bTRv6.webp) The blog template we are using ## Add a new CMS collection to store the blog post comments This Webflow template already has two CMS collections (blog post and blog post category). We are adding a new CMS collection with the name **Blog Post Comments**. This collection will have three attributes: * name: attribute of type plain text representing the comment author * message: attribute of type plain text * blog-post: will be a reference to the Blog Post collection, and will represent the post where this comment must be shown ![](/_astro/63d199b132ab33e662b1e6f9_Webflow-YepCode-Blog-Playground.BMYBd0K5_Z2pmQxG.webp) CMS collection to store blog post comments At this point, we could manually add some comment samples: ![](/_astro/63d19aa14cadc900da90dae1_samples.Ba1xiQw0_Z1En65S.webp) Blog Post comment samples ## ‍Change the blog post page template to render these comments Having this collection ready, we may go to the page where it must be included and add the collection item to show them. In our case, we have included a title (**Comments**), and then some containers and styles to display the comments list: ![](/_astro/63d19bfe858dad111fcf8831_add-collection.BvR2Jo6u_Z1scqGL.webp) Changes in blog post template page to include comments At this point, we need to add a filter over the collection, to make sure that only the comments related to the current blog post are included: ![](/_astro/63d19d1e84817e62aaefcb06_Screenshot-2023-01-25-at-22.17.19.Ce1yxNSo_ZeTPvM.webp) Add one collection filter to only include comments for the current blog post At this point, we have done all the needed changes to display the comments, but Webflow doesn’t include out-of-the-box any system that allow us to create CMS entries using their forms. So now is when YepCode enters to scene to allow doing this integration! ## Build a new YepCode process to create these CMS entries We’ll need to have a YepCode account to implement the process that will provide the form to embed and also all the logic to create the CMS entry with each submit. We can create a new YepCode Account using the FREE plan that is offered. Just go to the [registration page](https://cloud.yepcode.io/), and create your own account. Once into the platform, we just need to create a [new process,](/docs/processes) giving it a name: ![](/_astro/63d1a04b2019c13a0d21ca72_Screenshot-2023-01-25-at-22.33.55.D3amskXi_Z1wWvfz.webp) Create a new YepCode process After that, we may provide the source code that will implement the logic. For this sample, the [source code](/docs/processes) to use would be this one: This code example uses deprecated credentials: ```js const webflow = yepcode.integration.webflow('yepcode-blog-playground'); ``` Follow this [guide](/docs/credentials-migration-guide) to migrate your credentials. ```js const { context: { parameters } } = yepcode // TODO Change these two ids with your collection identifies const BLOG_POST_COLLECTION_ID = "63d015316533bf50728fa311" const BLOG_POST_COMMENT_COLLECTION_ID = "63d015e1d5eb3810e7e34985" const webflow = yepcode.integration.webflow('yepcode-blog-playground'); // We need to find the blogPostId using the blogPostSlug const {    items: blogPosts } = await webflow.items({    collectionId: BLOG_POST_COLLECTION_ID, }); const blogPost = blogPosts.filter((blogPost) => blogPost.slug === parameters.blogPostSlug)[0]; if (!blogPost) {    return {        status: 404,        body: {            error: {                message: `Blog post not found for slug ${parameters.blogPostSlug}`,            },        }    }; } console.log(`Creating comment for blog post ${blogPost._id}`) try {    await webflow.createItem({        collectionId: BLOG_POST_COMMENT_COLLECTION_ID,        fields: {            name: parameters.name,            message: parameters.message,            "blog-post": blogPost._id,            _archived: false,            _draft: false,        },    }, {        live: "true"    }    ); } catch (error) {    console.error(`There has been an error creating CMS entry`, error);    throw error; } return {    message: "CMS entry successfully created" } ``` Take into account that you’ll need to change the collection IDs for the ones of your Webflow project. You may find the collection IDs in each collection settings page: ![](/_astro/63d1a132fa703d43d8c8c48b_Screenshot-2023-01-25-at-22.37.45.Beg6_nXR_1kk2CH.webp) Find each collection ID and configure it in your source code The next step is to configure the [input parameters form](/docs/processes/input-params). This must be done in the second tab of your process configuration and is defined using a JSON Schema specification. In our case, the source code to use will be: ```js {  "title": "Share your thoughts about this post",  "type": "object",  "properties": {    "blogPostSlug": {      "title": "Blog post slug",      "type": "string",      "ui": {        "ui:widget": "hidden"      }    },    "name": {      "title": "Your name",      "type": "string"    },    "message": {      "title": "Your message",      "type": "string",      "ui": {        "ui:widget": "textarea"      }    }  },  "required": [    "blogPostSlug",    "name",    "message"  ] } ``` After setting this form source code, you should be seeing a form like this, that shows the name & message and also includes a hidden field for the blog post slug. ![](/_astro/63d1a24230ce1b34ebaacdad_Screenshot-2023-01-25-at-22.40.56.CKKfX0Fb_1Fa2IK.webp) YepCode process form previsualization The last step to build the YepCode process is to create our Webflow credential, that will allow YepCode to manage the CMS collections in your project. Just click on the new credential button: ![](/_astro/63d1a2d4091c1e355312d1e8_Screenshot-2023-01-25-at-22.44.27.D3u-ekb__Z1QwnqJ.webp) Create a new Credential And then follow the instructions in our [docs page](/docs/processes/input-params) to create the Webflow credential: ![](/_astro/63d1a2ecc496b215bbd77c12_Screenshot-2023-01-24-at-19.30.21.D18556z2_21hgHB.webp) Webflow credential including the API token ## Enable YepCode forms for this process Time to enable the YepCode form for this process. [Our docs](/docs/forms) include the needed steps to go to the process dashboard and enable the forms flag: ![](/_astro/63d1a443e6e745804ca9d540_Screenshot-2023-01-25-at-22.50.30.M8TrZ27q_ZxuAlu.webp) Enable Forms for this YepCode process After enable the form, you could see the source code that needs to be used to embed the form in any webpage. Copy it, because we are going to need in the next step. ## ‍Embed the form into the blog post page template Having done all the configuration in YepCode, it’s time to go back to Webflow and add an HTML embed component to include the source code that will render the form: ![](/_astro/63d1a51afa703d81b0c91872_Screenshot-2023-01-25-at-22.53.36.DBi_jtqv_1DXpnI.webp) Add one HTML embed component with form source code There are some changes from the provided code of the previous step. Every configuration option is detailed in our docs, and for this use case, we have added default values for the blog post slug hidden field, and also we have changed the [form theme](/docs/forms) to fit with our blog styles: ```js
``` To add the current blog post slug, we need to use the option **+ Add Field** that the HTML Embed component provides. We also need to include the snippet with our forms SDK, but instead of add it in this component, we are adding it in the page configuration for the `head` section: ![](/_astro/63d1a599df704b79c81f7049_Screenshot-2023-01-25-at-22.56.32.CmdOtEoV_ZtIsvX.webp) Add YepCode Forms SDK in page configuration ## It’s done 🚀 Time to test the full integration! To do that, it’s needed first to publish your Webflow site. After that, if you navigate to the published version and you go into one blog post page, you should see the comments form: ![](/_astro/63d1a7782b53c505a1530ec2_empty-form.CHwSSRGq_1BDhca.webp) Form embedded in the blog post page If you fill the form and click on **Submit**, one YepCode process execution will be done. If you go to YepCode dashboard, you could see it: ![](/_astro/63d1a86af65e7662e16d9e18_Screenshot-2023-01-25-at-23.08.26.DqLOVWf__Z1pknnM.webp) YepCode process execution for submitted form (I) ![](/_astro/63d1af9fbbb7a84270bcea6b_Screenshot-2023-01-25-at-23.39.10.CyhLbLA7_1H2lS2.webp) YepCode process execution for submitted form (II) Now, if you refresh the blog post page, you should see the new comment: ![](/_astro/63d1afe72b53c5090a5396f1_Screenshot-2023-01-25-at-23.40.30.D1C0gOi3_Z1V6aqy.webp) And that’s it! You have a fully featured comments’ module in Webflow and you only need YepCode, as no Webflow forms or webhooks are used, just an embed YepCode form. Take into account that this is only one example of all the potential of YepCode forms. You could achieve much more complex features, like read information from any external service and then show it in the page where the form is embedded. Don’t hesitate about contact us if you think this may help you to solve any of your information integration needs. # Wave scraped Zyte data to Airtable in minutes > In this article, show you how we can make use of YepCode Recipes to automate the movement of scrapped information using Zyte to any of the other systems we support in YepCode. In this article, we are going to show you how we can make use of YepCode Recipes to **automate the movement of information from Zyte** to any of the other systems we support in YepCode. Using the Zyte API, we can retrieve information from the scraped data and transfer it to any number of systems such as databases, MQ queues, Google Spreadsheets or an Airtable, for example. To depict this process, we chose a specific case involving the use of **Airtable**. ## But first, let’s address what Zyte is Zyte is a scraping service specializing in web data extraction. It focuses on removing complex technical barriers with little or no coding, enabling thousands of organizations to access valuable data that helps them make smarter business decisions, secure their competitive advantage and drive sustainable growth. The flow of our process will be to scrape data from a book store catalog using one Zyte account and store the results in Airtable. You can see the full details of this process in the next video, from cloning on of our YepCode Recipes to a fully functional process in YepCode: With YepCode recipes, we can move information between Zyte and many other systems in a very short time. All within our serverless environment. Happy coding! # Handle execution errors > In this article, we show you how to configure one YepCode Error Handler to get instant notifications when your process execution fails We have created YepCode to give you the best user experience, that’s why it has both fully development and execution environments. This makes it possible that you don’t have to leave the platform to create a complete and successful automation or integration. Once you have written the source code of your process in the editor and run it, the execution of this process may fail due to many circumstances: maybe some of your services is down, some credential has expired, your execution exceeds YepCode limits,… Whatever the case, you will probably want to be aware when this happens so that you can fix it. A practical solution may be to **send the error notification by mail or to a Slack channel**, but in any other cases you’ll want to **retry that failed execution**. ## YepCode allows you to configure one of your processes to handle errors when some execution fails We have recorded a video in which we show you how the YepCode error handler works. But let’s explain it a bit more. First, we have created a process that throws an error on purpose. When we run it, an alert crops up showing that the process has failed to show the error trace, and the execution status ends with an error. A process which you want to configure to handle the errors of the executions has a predefined parameters schema. In our docs, you can download some sample process templates we have, one that uses [Nodemailer](/docs/editor-config/js-editor/actions/sample-error-handler-with-nodemailer.json) to send an email with the error, and the other, which sends the error to a Slack channel using [SlackBolt](/docs/editor-config/js-editor/actions/sample-error-handler-with-slack.json) integrations. In the next step, we are going to download and import the send email template. Once imported, we need to create the SMTP credential to deliver the email. You could use one Google Account SMTP configuration. In our case, we are using the Sendgrid service. Then we need to do some changes in the source code to fit our needs, changing email addresses and YepCode team URLs. After that, we could configure this process as our error handler on the settings page. Finally, if we run again the failing process, we’d receive an email informing us about the error. Take a look at this video to watch all the steps to configure the error handler in YepCode and, Happy coding! [Handle execution errors | YepCode universe](https://www.youtube.com/embed/tCdzdW9tzOE) # Create Webflow CMS entries with form submissions > In this post, we'll show you how to connect your Webflow account with YepCode in order to create CMS entry items with form submission information. One of the **most requested features missing from Webflow** is the submission of form data to its CMS. ‍**Webflow is a very interesting tool for building websites** in a codeless approach. It **bridges the gap between developers and designers**, as it allows you to create mockups and prototypes in html and css and its drag & drop platform allows you to visualize and manipulate CSS parameters. Its CMS allows you to create hundreds of pages at a time thanks to its templates and also allows you to build collections to help you develop your business: launching your e-commerce, describing products and building forms to get customers more easily. With so many features, it would be obvious to think that it would also allow its **CMS to collect the information that a user puts into a form**. But unfortunately, this can’t be done directly with Webflow, yet. ## Striving for a smoother flow Some weeks ago, we migrated YepCode webpage to Webflow, and we are delighted with the result. We also included the Webflow integration (/docs/integrations/webflow/), and a bunch of recipes () to move information to and from this service. In this post, we’ll discuss [one of the most important aspects that Webflow lacks](https://wishlist.webflow.com/ideas/WEBFLOW-I-663). Send form submission data to CMS The basic steps of this guide are: * Create the CMS Entry you want to be managed * Create the form in Webflow to ask for the needed information * Create a YepCode process that receives that form information and creates using Webflow API the CMS entry * Configure Webflow to call the process webhook with each form submission ## Create the CMS Entry This is up to you. In our case, we are going to create a Pets collection. ![](/_astro/63696c3adb1f3c3fee2b13a1_Screenshot-2022-11-07-at-19.20.45.B-L0KyPE_13Dbfe.webp) ## Build Webflow form Create a new page adding the form. Include a field for each CMS Entry attribute, taking care to use the same name. ![](/_astro/63696d4373a040b06448c6ec_Screenshot-2022-11-07-at-21.39.53.DiycfRij_1Vzgo6.webp) ## Create the YepCode process Go to your YepCode account (you may create one for FREE), and create a new process using the following source code. This code example uses deprecated credentials: ```js const webflow = yepcode.integration.webflow("my-webflow"); ``` Follow this [guide](/docs/credentials-migration-guide) to migrate your credentials. ```js const _ = require('lodash'); const { context: { parameters } } = yepcode // TODO: Set your CMS collection id (it's available in Collection Settings window) const YOUR_COLLECTION_ID = "6366c9..." console.log(`Received execution parameters`, parameters) const formData = parameters.data const webflow = yepcode.integration.webflow('my-webflow'); function toLowerKeys(obj) {  return Object.keys(obj).reduce((accumulator, key) => {    accumulator[key.toLowerCase()] = obj[key];    return accumulator;  }, {}); } const createCMSItemBody = {  collectionId: YOUR_COLLECTION_ID,  fields: {    ...(_.mapKeys(formData, (v, k) => k.toLowerCase())),    "_archived": false,    "_draft": false  } } console.log(`Creating Webflow CMS item with parameters`, createCMSItemBody) await webflow.createItem(createCMSItemBody, { live: 'true' }) console.log(`Done 🚀`) ``` You should create a new Webflow credential with name **my-webflow**, and you must generate an [API key for a site](https://developers.webflow.com/#authentication). To do that, open the site in the dashboard and navigate to the “Settings” pane. There is a section titled “API Access”, where you can generate a new API key that must be provided in the token field. ![](/_astro/63696de10653f684f8e14aed_Screenshot-2022-11-07-at-19.23.30.CG4tEwbk_Q4lED.webp) You should also configure your CMS collection ID, that is available in your CMS collection page: ![](/_astro/63696f03d2aac70602f0b971_Screenshot-2022-11-07-at-21.47.53.B-aiaZ3C_Z13e3Y.webp) After that, you should create a webhook for this process, in order to be called from Webflow: ![](/_astro/63696f35c3bbd8847dff3446_Screenshot-2022-11-07-at-21.48.43.B0ANlZyT_1845ax.webp) ![](/_astro/63696f3da7b7aa84ce1ded6d_Screenshot-2022-11-07-at-19.23.44.BAaiiRxv_Z11GvI9.webp) ![](/_astro/63696f46b0ba0d4cbe2c022e_Screenshot-2022-11-07-at-19.23.58.CZLPt65r_Z2rzQRx.webp) ## Configure Webflow to call the YepCode webhook with each form submission Go to your project Integrations settings: ![](/_astro/63696f8c89b715e01c64e543_Screenshot-2022-11-07-at-19.21.44.B4FOynPc_CIc8c.webp) And create a new webhook for each Form submission. The URL to be used should be the one that YepCode provides with the webhook creation. ![](/_astro/63696f9edc9e7e19cef8bbd3_Screenshot-2022-11-07-at-19.22.20.BrtQ6zZQ_Z2qlWWA.webp) ### And that’s it! Just publish your Webflow site and visit the form page. Each submission will instantly create the CMS entry. ### Next steps This was just a sample use case, but you could complicate it as much as needed, adding more login to the YepCode process: retrieve information from any other service, also store the information in one external database ,etc Thank you for reading :) and… Happy coding! # Export Shopify orders to any database with an increment approach > In this case, we will export Shopify orders to any database using an incremental approach that collects, each time, the previous data. Today, we are going to see how to copy your [**Shopify**](https://www.shopify.com/) e-commerce orders data into a database. It will be [**MySQL**](https://www.mysql.com/) for this case. You probably are receiving many orders per day, so this copy process should be executed periodically to keep the database updated. For this reason, to be efficient, the process should load only the orders created since the last copy. We are going to implement this copy process in a few minutes using YepCode and some of its features: * We’ll start using a recipe from our [**recipes page**](https://yepcode.io/recipes). This will provide us with a code base that can be working with only a few changes. For this case, we’ll use the [**Shopify orders to MySQL**](https://yepcode.io/recipes/shopify-orders-to-mysql) recipe. * To perform an incremental copy, we need to store the last copy date somewhere. We could use a control table in our database. However, we can do it in a more efficient way using [**YepCode datastore**](/docs/datastore) for this purpose. This datastore allows you to CRUD key-value pairs in each execution of the copy process. ### Starting from the recipe First, we’ll create a new process using the [**Shopify orders to MySQL**](https://yepcode.io/recipes/shopify-orders-to-mysql) recipe. To do this, from the recipe page, click on **Clone to YepCode** button and then select your YepCode team. Click on **Create** and you’ll be redirected to the process page.In the process page you can see recipe source code. Looking along it you can see four blocks of comments, each one containing a **TODO** statement. Let’s review all of them! From top to bottom: ##### TODO: Create your Axios credential with Shopify information You’ll need to create a credential to be able to connect to Shopify API. So this TODO aims to create one. As the comment says, you need to provide your [**Shopify access token**](https://help.plytix.com/en/getting-api-credentials-from-your-shopify-store) by headers to be able to make requests to their API. You can create the credentials from the right sidebar, by clicking on the add button in the credentials section. Then select the Axios credential and fill in the needed info. Here you have an example of Shopify credential creation: ![](/_astro/633184022d1a563521361303_Screenshot-2022-09-22-at-12.17.55.D62Z8AwO_A9BIO.webp) Once you have created it, replace the credential name in the source code, just under this block of comments. For this example, you should replace *“your-shopify-credential-name”* by *“my-ecommerce-shopify”.* ##### TODO: Customize your request, checking the API documentation You may want to customize your request to fetch only the orders you need. For now, you don’t need to change anything here. This request will fetch all the orders. We are going to come here later. ##### TODO: Create your MySQL credential The same as for Shopify, you need a MySQL credential to be able to connect to your MySQL.Here you can see one example with the needed parameters for the MySQL credential. ![](/_astro/633184022d1a566571361304_Screenshot-2022-09-22-at-12.19.30.DXMgtNc8_ZN7eTN.webp) As in the previous case, replace the credential name in the process source code. For this example, replace “*your-mysql-credential-name”* by *“my-ecommerce-mysql”*. ##### TODO: Map your item to row and customize INSERT statement You need to modify the insert statement with your table name and store the desired item properties in your query. An example of the change in the code would be: ```js async consume(item) {    return await this.mysql        .promise()        .query(`INSERT INTO my_ecommerce_orders SET ?`, {            id: item.id,            currencyCode: item.currency_code,            email: item.email,            financialStatus: item.financial_status,            orderNumber: item.order_number,            processedAt: item.processed_at,            totalPrice: item.total_price        }); } ``` Now, after these changes, you’ll be able to copy all of your orders data to our MySQL database each time the process is executed. However, as we said, there will be new orders each day, and we don’t want to re-copy all orders each time we want to insert the new ones. For this reason, we’ll turn this process into an incremental copy process, which copies only the orders generated since the last process execution date. #### Make the process incremental To fit this requirement, you need to store the copy’s execution time and retrieve it in the next execution to fetch only the orders after that moment. You could use an auxiliary control table in your database, but YepCode offers a more agile way to reach this. This is using the data store. As we said, it allows to CRUD key-value pairs in each execution of the copy process. So, in each execution, we’ll retrieve the stored date of the previous execution, keep it in a variable and then update the same entry with the current date. Translating it to code, it looks like the code below, which you can paste at the beginning of your process source code: ```js const { DateTime } = require("luxon"); const LAST_EXECUTION_DATE_KEY = "shopify_to_mysql_copy_last_execution"; const lastExecutionDateAsISO = await yepcode.datastore.get(LAST_EXECUTION_DATE_KEY); // Update the datastore entry with current execution date yepcode.datastore.set(LAST_EXECUTION_DATE_KEY, DateTime.now().toISO()); ``` This is the moment when we come back to the second TODO, where it was not required to do changes before. Now, you need to customize the Shopify API request to fetch only the orders created after the last execution date. For this, you need to add the “created\_at\_max” query parameter, and set its value with the variable created in the previous step. The resulting code would be: ```js const {    data: {        orders    }, } = await this.axiosClient.get(`orders.json?status=any&created_at_max=`${lastExecutionDateAsISO}); ``` And that’s all, now you have configured an incremental copy process!! You can run it manually, schedule it or execute it via webhooks! Each time the process is executed it will only copy the orders generated after the last execution! ##### Next steps You have an incremental copy process, which was implemented in a few minutes!If needed, you could continue iterating this process to fit more needs. For example, you could send an email, telegram message, etc. with some info about the process each time it is executed. For this case, that info could be the total order price sum of the copied orders. We’ve done this for Shopify orders to MySQL, but this can be done for any of the services and APIs you can find in our [**recipes page**](https://yepcode.io/recipes)! You can browse there and find if there are more recipes which fit one need you have. Thank you for reading :) and… Happy coding! # Develop like a pro and get more control over your work thanks to YepCode CLI > YepCode has implemented a CLI that will give you more control over your computer and save you a lot of time. Today we are going to talk about a **brand-new feature in the YepCode** universe, our **CLI** and its importance in the development environment as a common and frequently used tool to operate and **speed up coding processes**. ### **But first, what is a CLI ?** CLI responds to the acronym of (**Command Line Interface**) and it is a program on your computer that allows you to create and delete files, execute operating system functions, run programs or navigate through your folders and files. Back in the 60s, CLI was the only way to communicate with computers, so developers used it frequently. Then the mouse would appear and the point-and-click method would begin as a new way of interacting with the computer. ### **Why a CLI in YepCode?** In YepCode, we have implemented the Command Line Interface that allows **interacting with your YepCode Cloud account from your workstation command line**. To implement it, we use **TypeScript**, relying on [**Oclif**](https://t.sidekickopen00-eu1.com/s3t/c/5/f18dQhb0S7kC8dDZCHW5dK2qR2zGCz1N5xLs7slrBrYW1S-5-y3cR5_6MXwSPM3ZvWtf21mVPW02?te=W3R5hFj4cm2zwW43P1nS3LD2rJ1V3\&si=8000000020810203\&pi=87dddb93-7237-40e9-c267-cb34e43c9970) and attacking YepCode’s **GraphQL API**. This may be very useful if you prefer to write and test the process’s source code in your local workspace instead of using the web IDE of YepCode Cloud. We follow a **GIT approach**, which allows us to run clone, execute pull & push commands and manage conflicts if someone changes process files in the cloud. The local copy of your team account will include **the processes source code**, **your js-modules** and also **the credentials & variables non-sensitive information.** ### **Some interesting use cases for YepCode CLI** ##### Sync your source code with a GIT repository All the source code you write in YepCode is yours, and although we [**support versioning**](/docs/processes/process-versioning), it may be interesting to **keep a copy** of it in some **GIT** repository. When you run the CLI clone command, a file structure is generated with all your file information. A *.gitignore* is also created, so just *init* your GIT *repo* and do a *push* to the remote server. ##### Avoid Yeps consumption during the development phases During the development process, you may be **trying executions to get the final implementation**. There is no problem with doing this in the YepCode cloud, but that executions If you prefer to save the yeps for the real executions, you **may develop in your local workstationand you will not consume any yeps**. ##### Integrate with CI/CD cycles YepCode Cloud doesn’t include testing features, but YepCode CLI opens a wide range of **options to check that your implementation is ok**. You may **install the CLI in your CI/CD platform and run some processes with test parameters** (for example the environment). If the test executions finish ok, then you may automate the *push* command to the YepCode Cloud. We believe the YepCode CLI will give you more control over your computer and is a powerful time saver. Check it here and learn [**how to install YepCode CLI**](/docs/cli/) in your team account. Happy coding! [Develop your processes more efficiently | YepCode CLI](https://www.youtube.com/embed/Pggg84OLwnQ) # Solve common problems and connect your services and APIs even faster with YepCode recipes > Discover YepCode recipes, our series of code snippets to connect your services and APIs and solve common problems faster. Today we are going to discover a new piece of the YepCode universe. We are talking about our **YepCode recipes**. These recipes are **templates** made up of **pre-built code snippets** used in many popular scenarios that will allow you to **start implementing a process in an agile and easy way**, instead of facing an empty source code editor. Basically, we have a YepCode recipes [**gallery with many templates to build your integrations**](https://yepcode.io/recipes/) with thousands of apps and you can adapt them to your needs. You can browse our platform to find the **best recipe to connect your favorite apps and improve your workflows**. There are recipes for building your **ETLs**, pushing information from your **database** to any **API**, automating **reports** generation, fetching info from your **e-commerce** database, syncing your **CRM** with your database, automating **e-mails** and much more. ### **Let’s see an example of YepCode recipes** Now we are going to show you **how to work with one of our YepCode recipes**. For that reason, we are going to use a recipe to create a process that performs a movement of information between [**MySQL**](https://www.mysql.com/) and [**ClickHouse**](https://clickhouse.com/) in a very short time. The steps to make a recipe work are very simple: 1. Search 🔎 for the one you are most interested in 2. Clone 🖨 it on your team by clicking on ‘Clone to YepCode’ 3. Create the necessary 🔐 credentials 4. Adapt the source code 🧑‍💻 to meet your exact needs 5. Run the process 🚀, schedule it 🕙 or start executions using webhooks! In short, we have just taught you the best way to start using YepCode recipes. However, to get familiar with its use, we recommend that you do the following steps by yourself, so here is a **video showing how the complete example was made**. Don’t miss it. Enjoy it and… happy coding! 😉 # Avoiding Vendor lock-in to harness all the potential of your code > YepCode allows you to save and export the code created when you finish a process avoiding the annoying Vendor Lock-in As companies continue to grow, all of their **processes become more and more complex** and need to be executed as quickly as possible to increase their productivity and revenue (that’s the raw truth). **Time reduction is a challenge** that many growing technologies, such as **low-code development or IDEs**, have to deal with every day. But why are companies still reluctant to incorporate this type of tool into their day-to-day activities? Well, some of the reasons may be the **lack of knowledge** on how to use them. They may also think that these solutions \*\*lack flexibility.\*\*Their **security** also raises some doubts, as well as their potential **scalability**. Today we are going to talk about another one, the **vendor lock-in** ### **¿What is Vendor lock-in?** One of the main **fears that discourage organizations from adopting new technologies** such as low-code apps, IDEs and other Saas platforms to code their processes is the vendor lock-in. ‍**Vendor lock-in** refers to [**a situation where the customer is dependent on a single vendor**](https://en.wikipedia.org/wiki/Vendor_lock-in) and remains stuck to it **due to the high costs** of switching to a different vendor. These costs can be not only economic but also technological. For example, think of **SIM cards** that only work with one carrier. Switching between companies is difficult for customers in many cases. Another example can be **capsulecoffee machines**. If you want to change the coffee or the company changes the design of the capsules, you will have to change the machine with the cost that this entails. ### **Main risks and consequences of Lock-in** A closed, proprietary and inflexible solution usually implies the loss of control by the client, over data, infrastructure and security. **Relying on a single vendor may be risky when we have a critical response**, availability, or security needs. Because that implies blindly trusting the vendor, a relationship that takes time to build. In case of a **critical failure**, a strong dependence on a single provider can harm us and leave us without alternatives to be able to react. Needless to say, the high cost that this can imply. Vendor lock-in can become an issue in **cloud computing** because it may be very difficult to **move large volumes of data** between databases once they are set up. Especially in migrations, where we need to move data to an entirely different type of environment, this may involve reformatting that data. Another potential danger is the **business decisions** that the company may adopt, such as price increases, changes in offerings or a decrease in the quality of the service to seek lower prices. In those cases, the **client will not have bargaining power** and will remain tied to the company. ### **How YepCode avoid Vendor Lock-in?** As developers, we are fond of **Clean-code** and the **Open-data** philosophy. We like that our users use our platform, **find the value that YepCode can bring to their team and in their daily work** by themselves and not be tied down. As you may find in our[Docs platform](/docs/), to implement a process in YepCode you need to write **JavaScript** code (using **NodeJS** as execution engine). The platformallows you to**save and export the generated code**, so if at any time you prefer not to use our execution environment but to configure a new server from scratch and execute the code there, you can do so. However,all the hypervitaminized functionalities that we provide would not be available(credential storage, webhooks, tunneling, integrations, speed, power and versatility)… This, in principle, can be counterproductive for us, but we are sure of the **value that YepCode can bring to our users**. Happy coding! # How to share a Slack thread content by email > We show you how YepCode can help you export the conversations generated in Slack and share them with other teams via email. [**Slack is widely used in customer support teams**](https://slack.com/intl/es-es/), as its integrations with CRMs make this messaging tool the perfect way to be aware of several conversations or tickets. Sometimes, it may be necessary to **export the information generated** there to share it with other teams (ie: technical support). In this post we’ll show you how YepCode may help in this task, **creating a process that delivers by email the content of a slack thread.** To run this example we are going to need a YepCode account (it’s free!) and to be a Slack admin of one workspace. ### Creating the YepCode process * Open your [team workspace](https://cloud.yepcode.io/) in YepCode * Click on ***New*** button in the processes page * Choose a name and a description ![](/_astro/63318402f31eab3e6a064449_Screenshot-2022-05-18-at-18.31.42.CJoMd6qV_1a1PSJ.webp) You will be redirected to the process page. Don’t worry about the code of the process, we are going to deal with that later. Now we are just going to **configure a webhook** on this process so Slack can communicate with it. * Click on ***Add+*** button in the right sidebar, next to *Webhook configuration* * Don’t fill basic auth options, we need this webhook to be public * Click on ***Create***! Perfect! A modal will prompt you with webhook info: the important thing is the **URL link.** We will need it later to configure our Slack Shortcut! You always can come back to the *Webhook configuration* to copy the **URL link**. ### Creating the Slack App To create your own Slack App open your [app’s dashboard](https://api.slack.com/apps) and click on ***Create New App*** button. You only need to choose a name and a workspace. ![](/_astro/63318402f31eab436106444c_Screenshot-2022-05-18-at-17.43.41.DICGHQwD_1fwvjL.webp) Excellent, we have a brand new Slack App! We are going to use [Slack Shortcuts](https://api.slack.com/interactivity/shortcuts) instead of [Slack Commands](https://slack.com/help/articles/201259356-Slash-commands-in-Slack). Why? The reason is that you can’t use commands inside a thread, instead, [message shortcuts](https://api.slack.com/interactivity/shortcuts/using#message_shortcuts) are options that are shown in any message context menu. ### So… how do I create my Slack Shortcut? * Open your [app’s dashboard](https://api.slack.com/apps) * Click on *Interactivity & Shortcuts* in the sidebar * Enable *Interactivity*: It will ask you for a **Request URL**, paste here our webhook **URL link** from our YepCode process. * Click the ***Create New Shortcut*** button under *Shortcuts* * Choose On Messages option and click ***Next*** * Fill in a name, a short description and a callback ID. * Click that tempting green ***Create*** button, and you’ll be sent back to the *Interactivity & Shortcuts* page * On that page don’t forget to click the ***Save Changes*** button! ![](/_astro/63318402f31eabb1c706444f_Screenshot-2022-05-18-at-18.26.32.BeEeyRIH_ZoGXzD.webp) Now we need to configure an access token to communicate Slack and YepCode and add some permissions to the bot ##### Configure OAuth and Permissions * Open your [app’s dashboard](https://api.slack.com/apps) * Click on *OAuth & Permissions* in the sidebar * Click on ***Install on workspace*** button under *OAuth Tokens for Your Workspace* * Click on ***Allow*** button so Slack to confirm * You will be sent back to *OAuth & Permissions* where now appears a *Bot User Auth Token*. We are going to need it to configure a credential on YepCode. * Scroll down in *OAuth & Permissions* to *Bot Token Scopes* section. we are going to add two new permissions: **channels:history** and **users:read** * **Reinstall the App** for the changes to take effect ### Implementing the Magic on YepCode We’ve finished configuring our App in Slack, so let’s go to YepCode to make it all work. First, we are going to **create** **two credentials**, one to store Slack tokens in a secure way and the other to store our SMTP configuration. * Open your [team workspace](https://cloud.yepcode.io/) in YepCode * Click on *Credentials* in the sidebar * Click on ***New*** button * Select *Slack Bolt* integration type * Fill the following fields: 1. *Credential name*: it’s the unique identifier for the integration with slack i.e.: *thread-exporter-slack* 2. *Signing Secret*: Grab your Slack Signing Secret, available in the app admin panel under Basic Info 3. *Token*: This would be the *Bot User Auth Token we’ve created* on *OAuth & Permissions* Click on ***Create*** and there you go! It will appear in the Credential list ![](/_astro/63318402f31eab26f006444e_Screenshot-2022-05-19-at-10.51.40.BOfVt4qF_2bvDrM.webp) Create another credential. This time we are going to connect our SMTP so we can send mails later. * Click again on *New* button on the *Credentials* page * Select *Nodemailer* integration type * Fill the fields with your SMTP info. You could use your Gmail account to test it. ![](/_astro/63318402f31eab53a906444d_Screenshot-2022-05-19-at-13.01.14.9bkM0Oyp_s4yOt.webp) #### The YepCode process Congrats! We are close to finishing. We are going to implement the logic that will read the messages from Slack and send them to the support mail. Navigate to the process that you created in the first step. This is the full code, we are going to comment on some parts, but if you are feeling lucky you can execute right away! Write and save the following lines in the code editor: This code example uses deprecated credentials: ```js const nodemailer = yepcode.integration.nodemailer('example-gmail') const { client } = await yepcode.integration.slackBolt('thread-exporter-slack') ``` Follow this [guide](/docs/credentials-migration-guide) to migrate your credentials. ```js const {  context: { parameters } } = yepcode const { callback_id, channel, message_ts, message } = JSON.parse(  parameters.payload ) console.log('Received interaction', callback_id) const nodemailer = yepcode.integration.nodemailer('example-gmail') const { client } = await yepcode.integration.slackBolt('thread-exporter-slack') client.conversations  .replies({    channel: channel.id,    ts: message_ts  })  .then(async ({ messages }) => {    console.log(messages)    const userIds = [...new Set(messages.map(({ user }) => user))]    const users = await Promise.all(      userIds.map(async (user) => {        const {          user: { name }        } = await client.users.info({          user        })        return { id: user, name }      })    )    const emailText = messages      .map(({ text, user }) => {        const userInfo = users.find((u) => u.id === user)        return `${userInfo.name}: ${text}`      })      .join('\n')    console.log(emailText)    const info = await nodemailer.sendMail({      from: 'yepcode@example.com',      to: 'support@example.com',      subject: `New slack thread: ${message.text}`,      text: emailText    })    console.log('Sent email', info)  })  .catch(console.error) ``` To **invoke this process** go to your Slack workspace and click on the context menu of a message, it will appear your Shortcut, in my case is *Send to support.* **Important!** You need to invite the App to the channel: You can do it simply by typing the following message: */invite @Thread exporter* ![](/_astro/63318402f31eab0d1806444a_Screenshot-2022-05-19-at-11.14.45.DvSrKq8N_ZqD6Kc.webp) After you click, go back to YepCode and navigate to *Executions* on the sidebar. It should be a new execution! Click on it and you should see something like this. ![](/_astro/63318402f31eab494b06444b_Screenshot-2022-05-19-at-11.12.54.BLlKl3v8_Z2op4Y.webp) If you see something like this, congrats! You’re done. If not, review the previous steps to see if something is missing. Let’s review the code! ```js const {  context: { parameters } } = yepcode const { callback_id, channel, message_ts, message } = JSON.parse(  parameters.payload ) ``` Here we are getting the information Slack is sending to YepCode. There are a lot of fields but we only need: * callback\_id: Just to know which interaction is calling, it will match the Callback ID of the Shortcut we’ve configured. * channel: the unique identifier of the Slack channel * message\_ts: the unique identifier of the Slack message that was clicked on * message: the full info about the message that was clicked ```js const nodemailer = yepcode.integration.nodemailer('example-gmail') const { client } = await yepcode.integration.slackBolt('thread-exporter-slack') ``` These two lines use some YepCode magic: they initialize our integrations, the first for [Nodemailer](/docs/integrations/nodemailer) and the second for [Slack Bolt](/docs/integrations/slack-bolt). Both use their respective credentials. ```js client.conversations  .replies({    channel: channel.id,    ts: message_ts  })  .then(async ({ messages }) => {    //  })  .catch(console.error) ``` We ask for the conversation messages related to our clicked message in the specified channel. If you remember we had to add a special permission **channels:history** in our Slack App, this is the reason. The request returns the messages that we are going to consume. ```js const userIds = [...new Set(messages.map(({ user }) => user))] const users = await Promise.all(  userIds.map(async (user) => {    const {      user: { name }    } = await client.users.info({      user    })    return { id: user, name }  }) ) ``` We need some user information like username or email. It’s a pity but this info is not in messages, we need to ask for it to Slack. This is the reason we added users:read permission in our Slack App. We get all userIds in messages and make a request per user saving them in the users variable. ```js const emailText = messages  .map(({ text, user }) => {    const userInfo = users.find((u) => u.id === user)    return `${userInfo.name}: ${text}`  })  .join('\n') console.log(emailText) const info = await nodemailer.sendMail({  from: 'yepcode@example.com',  to: 'support@example.com',  subject: `New slack thread: ${message.text}`,  text: emailText }) console.log('Sent email', info) ``` This is the final code. We mount the email text concatenating the username and the message text. Once we have the string, we just need to use the method sendMail of **Nodemailer** to send it to . That’s it! You are ready to go! This is just a *simple* example of Slack Shortcuts using YepCode but we could add more logic to it. For example, it would be awesome to ask the email to send the thread, this can be done using [Slack Bolt](/docs/integrations/slack-bolt) and [Slack modals](https://api.slack.com/block-kit/building). Thank you for reading :) and…Happy coding! 😉 # Sync your Apollo.io contacts with your database using YepCode > We have created an integration to retrieve information from an eCommerce database and then upload it to Apollo.io, a sales intelligence and engagement platform. If you want to **sync your Apollo.io with your database**, you will probably run into some issues that may make this task not as simple as it seems. Especially if you want to **automate this process to keep this database up to date** as new contacts are made. In this case, we’ll show you a complete implementation of a process inYepCode, **from account creation to fully working**. The process will consist of creating an integration that **retrieves information from an eCommerce database** (in this case, a **MySQL server**) and using a **REST API, uploading the retrieved information to Apollo.io.** ### **But first of all, what is Apollo.io?** [**Apollo.io**](https://www.apollo.io/) is a sales intelligence and engagement platform which allows you to **search and store new contacts to improve your B2B salesprocesses**. It also lets you **automate emails**, calls, and tasks to maximize efficiency and speed up your sales. With Apollo, you can **search for new contacts** as you can **connect to LinkedIn to find verified email addresses and phone numbers**. You can also store them in your database and sync them directly with your CRM. ### **What is the starting situation for having to sync Apollo contacts with our database?** Our initial situation is this: We have an **e-commerce database** with the information of our clients. We want to have that **information in our Apollo account, to set up some email automation sequences** to send those customers new product offers. Also, in this process, we want to **deliver an email report with the contacts uploaded.** So to show how to implement a full process in YepCode we are going to **build the process from scratch** by creating a brand new YepCode account. ![Contacts database to Sync Apollo.io with your database](/_astro/63318402300b97dd0e433b45_Ecommerce-DDBB-1024x662.CQMqQ7or_Z1Jqf7c.webp) ### **Let’s go to the process.** Once we’ve created a new account, you can see there are some sample processes you can interact with, but we’re going to **create a new one.** This process will **query the database**, **upload the logs** using the Apollo.io API and **send the e-mai**l with the processed information. So, we are going to start by giving the process a name and description. Next, we need to **write the source code** for the process, **configure the input parameters** and we can also **write some documentation** for the process in a ‘markdown’ format. The first step here is to **retrieve the client’s information from our database**. We are going to **build a flexible approach by requesting an SQL filter to build the query to retrieve our clients.** > This integration would take hours to be implemented and would be very difficult to do with a nocode tool.- Marcos Muíño (YepCode founder) We need to go to our [**parameters schema configuration**](/docs/processes/input-params). You can use some **snippets** to see the **JSON schema** that allows us to build the form but we already have the sample pre-build. At this point, we are going to ask for the “SQL wherefilter”. With a default value which filters by country and limit. Having this filter configured, in the source code we **need to access the YepCode parameters**. (As you can see, YepCode has some Snippets integrations). Here we have our **MySQL client** and we need to provide **credential** information. In this case, we are going to play with a playground credential. In our **documentation**, you can find all the necessary information to know how to build that **credential connection**.To configure the **MySQL credential**, we will go to the credentials section and create a new one. We’ll provide the name, our host, the user, also the password, the database and finally the port. The next step will be to **retrieve the clients from the database**. As we have seen before, we already have the SQL filter, so our **source code** could be something like this. ![Source code to sync Apollo.io with your database](/_astro/63318402300b9795d5433b40_Source-code-to-retrieve-clients-from-MySQL-database.C1Wgkl8D_ZCs52u.webp) Now that we have the client, we will **build a query against our database client**. We will also **add the SQL filter** and then close the connection. If we run this process, we will see the retrieved clients from our database. ### **Uploading the information to the Apollo account** Our next step will be to **upload the information to the Apollo** account. To achieve this, we are going to **add a new execution parameter** with the Apollo list where we want to store the new contacts. So we add a new parameter that we will call ‘apolloContactsList’. And when we’re done, we’ll see **another input parameter with a default value.** Now we need to **configure the credentialfor the Apollo.io API**, which will be an [**Axios**](/docs/integrations/axios) one. We provide the name, the base URL and some **HTTP headers**. We can now use our credentials to **iterate over the retrieved clients in the MySQL database.** For each client, we will display the first name & last name in the console log and then perform a **‘post’ request against the Apollo API**. We need to provide the APOLLO.IO API KEY. The Apollo authentication can receive the API KEY as a query param. ### **Now, we’ll create a variable** So we are going to use another YepCode feature, which is the [**Variables**](/docs/processes/team-variables). We will create a new one with the name **APOLLO.IO API KEY**. Then we have to go to our Apollo account. In the integrations section, in the API, we will copy our key. We will then **place it in the Apollo environment variable**. We are using the **contacts method** as you can see in the documentation where you also find every single piece of information. Once this is done, we can try another execution to check that everything is ok. For example, we are going to filter by SPAIN and only ask for four records. We can verify that all four contacts have been uploaded. If we now go to our Apollo account, we can see that **a new list has been created** and it has the four contacts that we have found in our database. ![Apollo contacts synced after running process](/_astro/63318402300b9730d9433b41_Apollo-Contacts-1024x567.QVBcb6Hc_xphuk.webp) ### **Setting up the e-mail report delivery** To **send the e-mail report**, we need to **create a new credential** (in this case an **SMTP server**), and then write the code to deliver the e-mail with the desired content. So we will start **configuring the Nodemailer credential** by introducing a server (in this case we’ll use **MailCatcher**) that will allow us to perform some tests against mail servers. If we go now to our process we need to deliver the e-mail. We could use some snippets but we already have the source code here. We will **set up the Nodemailer credential** and then we are going to build the e-mail that we want to deliver. These **e-mail addresses** could also be configured in the input parameters, but for this case, **we already have them in the source code**. We can try another execution, filtering, for example, by Japan and showing us seven contacts. If we now go to our ‘MailCatcher’ we can see **the mail and the new contacts**. We can also see each contact with their address in Apollo. This integration could be implemented for any business need, forgetting all the tasks related to the systems infrastructure. ### **Additional settings** Once the whole process is done, we could configure a [**periodic execution**](/docs/executions/scheduled) but it would be necessary to make some changes in the source code to load only clients not previously loaded. Another interesting approach would be to [**configure a webhook**](/docs/executions/webhooks) that allows this execution to be started from other systems. ### **Implementing the inverse process** Implementing the **inverse process** would be quite straightforward. So we are going to **retrieve the Apollo contacts and then transfer them to our MySQL database**. The **input parameter that we are going to use is a keyword**. We are going to ask the user for a keyword that would be used to search contacts in Apollo. The source code for this process will be quite similar to the previous one. We retrieve the YepCode parameters. **We will need the Apollo integration** but we don’t have to define it again cause we already have it from the previous process. Now we **perform a search request**. (You could see in the Apollo API where this search method is available.) We are going to use the **contacts search method** that allows us to provide some keywords that will be the ones from the parameters. Having the Apollo contacts downloaded, we **start the MySQL credential** and we perform the insert in one existing database. We will run now one execution, for example with YepCode with five contacts. We will create each row with the email and the name. **Then we will store the full JSON content** that Apollo provides us. We can try another execution with 11 contacts and then we can find them in Apollo. This is a sample of how to use [**the full power of YepCode**](/blog/an-overview-of-yepcode-technology-stack/) to solve your integration and automation needs. Remember that our [**Docs platform**](/docs/) includes every single detail to make the most out of YepCode, Enjoy the video and… Happy coding! 🧑‍💻 # Employee onboarding flow automation to save time and avoid mistakes > Thanks to a YepCode process you can automate your new employee onboarding flow saving time and avoiding human error. When you hire new employees, it is not an easy task to have a **successful onboarding process**. There is a lot of paperwork to do and, depending on the company, it may be necessary to **register them in multiple systems** (email, ERP, PM System, database, etc). In fact, if your company is not big enough to have its own human resources department. You will need to dedicate **valuable time from other team members to accomplish these tasks.** Let’s look at an example of a technology company that was able to **succeed, save time and minimize human error** by automating this employee onboarding process. ### **Automating the employee onboarding flow of a tech-company** [**Trileuco Solutions**](https://trileucosolutions.com/en) is the software development company behind YepCode. They were born in 2010. Today they have a **team of developers** passionate about technology who have a wide range of skills in the most popular programming languages, including Java, C++, Python, PHP, and JavaScript.Among their services, they offer **mobile and web application development**, as well as custom development, design and **consulting**. They focus on delivering high-quality products and developing **custom software solutions** to meet their customer’s business needs. ### **How can the automation of the employee onboarding flow help you?** Currently, they have over 30 employees. Although their rotation ratio is not quite high, **each new employee onboarding is quite time-consuming,** creating accounts over several systems and services. In the same way, every time they have an **offboarding**, they must remove that user account from many systems, making sure that person has no longer access to their systems. Their legacy approach to solving this was to have the documentation properly updated in a Notion document. However, that was **causing their IT and HR teams to perform manual tasks** on whatever services users should have access to. This could also **cause some human error** which they should try to avoid. With the irruption of YepCode, they decided that a great use case could be to **automate this onboarding flow.** To do so, they had to create a process that would accept the **new employee’s information** (name, email, services and roles), and **perform the necessary changes in each related service to create and configure that user account.** In the same way, they could **automatethe offboarding flow.** Simply by requesting the user’s email, and **removing the necessary information from each system.** ### But is it always necessary to automate this onboarding process? Let’s go through our process. Some of the systems involved in this case were **Keycloak** (which is their identity provider. But any other solution like **Ldap**, **Okta** or **Auth0** could be easily used with their integrations). They have a git repository (they use **BitBucket**, but other services like **GitHub** or **Gitlab** could be integrated). **Mattermost** (is their IM). They use **Redmine** as their project management tool. They have one internal app for **absences management.** And finally, they have all the **Kubernetes** cluster-related services (Prometheus, Kibana,…). > Now we can streamline the onboarding process of our new employees, achieving a better landing experience at Trileuco. -*César Suárez (Head of People)* So far, they have already integrated most of their services with their identity provider. So that, the signup in that service simplifies the user creation. However, with the others, it **is required a fine-grained configuration** that they have done with each **service API** or directly with changes in the needed databases. After this process implementation, the HR team only has to **ask supervisors what roles each new employee should have.** Then\*\*,\*\* they can **configure it with the input parameters form** in the onboarding execution. For the **offboarding process**, the only parameter required is the e-mail. After the execution, all the user accounts are **disabled in less than a minute**. And this is how **YepCode can help companies** in their daily work by [**automating any task that may slow them down**](https://yepcode.io/using-yepcode/holded-documents-signature/). Remember to visit our [**Docs platform**](/docs/) where you can find every single detail to make the most out of YepCode. Happy coding! 🧑‍💻 # How to automate your Holded documents signature using an eSign provider > In this case, we show you how you can use YepCode to automate your Holded documents signature and streamline your administrative paperwork. In this case, we will proceed to **automate an estimate document signature** using Holded as a platform for generating, downloading and storing that document. This time we will use **Docuten** as an **electronic signature tool**, but we have also implemented this use case using **DocuSign**. Holded is a [**cloud business management platform**](https://www.holded.com/) that allows you to carry out administrative procedures. With Holded you can have all your **data**, such as **documents**, **invoices**, and **customer information centrally** **controlled.** You can also associate this data with specific projects and share them among members of the same team. This tool, also allows you to control the **management of your billing**, **accounting**, work teams, and **projects.** And it has **CRM features**. Additionally, Holded **integrates with other third-party tools** thanks to its API. This makes its functionalities even more extensive and allows it to **automate processes** involving other complementary applications. ### **What is the workflow to automate Holded documents signature?** Imagine this situation: One company sends another a quote for hiring their services. The **workflow** begins when the sales department prepares and generates a **document of this quote in Holded**. From there, they send it to the client for review and acceptance. When the **client accepts the quote**, the sales department has to notify the administration department to **download** the estimate document **from Holded.** Then, they **upload it to their eSign provider** (in this case we’ll use [**Docuten**](https://docuten.com/)). And from that tool, they send it to the client for **final signature**. Once signed, the eSign provider sends a notice to the **administration department**. When this is done, they will have to **download the signed document** and send it to the sales department. In the final step, the sales department will have to upload it again to Holded to file it and **assign it to the corresponding project**. This is a process that would take **considerable time.** It has **many** **bottlenecks** where delays can occur as it is very easy to miss the notices between sales and administration. > With this process, we solve just in minutes what before would take us days.- Felipe Peña (Tracktherace CFO) ### **How do I proceed in YepCode to implement this process?** In order to automate Holded documents signature in **YepCode,** **we have to define two processes.** One to **launch the signature** request and another to **handle the eSign provider callbacks** once the client has signed the quote. ![Budget signature automation processes in Holded](/_astro/63318401f31eab52b2064437_2-processes-to-automate-budget-signature-in-Holded.D-u_o-9g_18fHEI.webp) To launch a new signature request, we will simply execute the first process. We will **enter the quote Id in Holded as a parameter** and optionally we will **indicate the email and name of the person responsible** for signing (in another case, the data of the person responsible for the client associated with the quote in Holded). ![](/_astro/63318401f31eab0ed506443a_Budget-signature-automation-Holded-ID.3OgNqFeE_25WBe9.webp) We will launch the second process [**thanks to the** “**webhooks**” **functionality**](/docs/executions/webhooks) provided by YepCode and **the Docuten service will automatically invoke it** when the client has signed the quote. In order to implement the processes, we have defined three “**credentials**”. For two of them, we will use the **integration with Axios** for access to the **Docuten and Holded APIs** (where we configure our access token to them). In the third, we will use the **integration with Nodemailer** (with our access data to **SendGrid** that we will use to send notifications by email from the processes). ![](/_astro/63318401f31eab5e75064438_Budget-signature-automation-with-Holded-YepCode-credentials.CgVTgtP0_Z82dVP.webp) Some code usage examples of these integrations: ![](/_astro/63318401f31eab895906443b_Process-Getting-budget-document-pdf-from-Holded.wfcNpvcG_1x6qcz.webp) ![](/_astro/63318401f31eab683b064439_Process-Retrieving-info-for-signed-doc-from-docuten.Dw0s4iqi_Z1j9sC3.webp) Finally, we will also make use of the **variables function** to **parameterize the processes.** By doing this, they can be **imported and other clients could use them** according to their own needs. ![](/_astro/63318401f31eab2e1906443c_Automate-sign-budget-with-Holded-Team-variables.B92rtwfX_Z1VRBtc.webp) And that’s all. We have reduced a considerable amount of time by creating this process (around 75% of the time), since with a few clicks we can solve the electronic signature of an estimate. This demonstrates YepCode’s ability to [**connect with other platforms and create automations**](https://yepcode.io/using-yepcode/docuten-extended-saas-features-using-yepcode/) to speed up day-to-day tasks. Remember to visit our [**Docs platform**](/docs/) where you can find every single detail to make the most out of YepCode, Happy coding! 🧑‍💻 # NodeJS streams to solve a data movement problem, minimizing memory and increasing speed > We solved a data movement problem while minimizing memory consumption and with high-speed transfer data rates thanks to a NodeJS Stream system and FTP and SQL server integrations. As you may know, YepCode uses **JavaScript** as programming language, and **NodeJS** is the current execution engine.We are working to support other languages like **Python** or **Go!** in the future. NodeJS is an open-source, cross-platform, single-threaded **runtime environment** for building **fast and scalable** server-side and network **applications**. It uses a non-blocking, event-driven I/O architecture, making it efficient and **suitable for real-time applications**. One of the advantages of using NodeJS is that it allows you to **handle a large number of simultaneous connections with high performance**. It is fast, efficient and widely used for **Chatbots**, **Streaming** applications (Netflix uses it!) and **IOT**. As seen before, moving information between applications can be an extremely tedious task, especially if [**we are dealing with large volumes of data**](https://yepcode.io/using-yepcode/how-to-automate-efficiently-data-movements-from-google-bigquery-to-snowflake/). Today we bring you an example demonstrating how YepCode can solve a data movement problem while **minimizing memory consumption** and **with great transfer data rates.** ### What can I use a NodeJS Stream for? A Stream is a flow of information that programmers usually use to **transfer data**. ‘Streams’ were built to **handle data in real-time** through a buffer. Their main advantage is that **you do not need to store the entire data in memory** at the same time, but parts of this data. So it can also process file streams that can be read in parts without their full context. Streams are very useful when we need to **query information** that comes **from multiple data sources**. This sample shows one need that one of our clients had, as they needed to [**download a CSV file**](/docs/libraries/request), [**process each CSV line**](/docs/libraries/csv), convert each entry to a JSON format upload it to an [**FTP server**](/docs/integrations/sftp) and also insert each row in a [**Microsoft SQL Server**](/docs/integrations/mssql) database. This use case could be a full project created from scratch, but with YepCode, and some dozens of lines of code, it’s done! The YepCode **integrations used have streams support**, so we are able to create a stream from the file URL, **pipe** the content to a transformer that **converts each entry to a JSON**, and in parallel, **pipe that JSON to the FTP and SQL Server integrations**. All the process is extremely **fast** and with no memory consumption! ### Watch how to execute this Stream process in the next video If you watch the video below, you will see an example of the execution of this process. As you may see, we copy the **URL** and when we hit the execution, **italready asks us for the URLof the file** that we include. We run it and this is already processing all the data. As we have said before, the process does not load all data in memory. You can also observe that the **process has finished successfully**, **processing** the entire **89 rows**. If you now go to the **FTP server** we will see that **the generated JSON data is here**. Here you can also see that the process has converted the **.CSV to a JSON** format. And finally, if you go to the **SQL Server Database**, you will see that we have 89 records. Remember that our [**Docs platform**](/docs/) includes every single detail to make the most out of YepCode, Enjoy the video and… Happy coding! 🧑‍💻 # How Tracktherace used YepCode to retrieve GPS SPOT data and push it to their platform > YepCode was able to retrieve GPS data and display it on the Tracktherace platform in a location with difficult coverage due to challenging orography. ### First of all, what is Tracktherace? Tracktherace is one of the big players on [**GPS tracking for sports events**](https://tracktherace.com/). It offers a comprehensive service that helps to **level up sporting events** by providing benefits in four different areas: security, tracking, management and promotion. Its basic operation is simple, although there is a lot of work and complexity in its internal development. The platform **combines the power of GPS tracking devices with real-time tracking software** that displays the position of these devices on a **map view**. This allows, in addition to **seeing the position of each participant in real-time within a race**, to process that position data to generate advanced statistics such as classifications, waypoints, provisioning, stoppages, etc. The devices also have an SOS button, which will display a highly visible, flashing prompt on the map view once pressed. This allows organizers to **act quickly in case of an emergency**. Tracktherace can be adapted to multiple sports disciplines. However, it is **especially useful in long-distance endurance races** such as trails, ultra-trails, adventure races, mtb ultramarathons, etc. In this type of sporting event, both the duration and the orography of the terrain make it very difficult to know what is happening. Tracktherace also allows the **event to be brought closer to the public** since, due to the conditions, it would be very difficult for them to be present on site. ### How Tracktherace really works? The company has a stock of more than **1000 GPS trackers** that **receives positioning** **information from GPS satellites and forward that information to a cloud server using TCP connections**. That server implementes the devices protocol, and process the received information saving the positioning information in their database to be used later in the race map view, the classification and dashboards calculations,… This kind of device **uses the GPRS network protocol** to deliver the information to the Tracktherace servers. But there is an issue here, if there is no phone coverage, the system can’t work in real-time. Luckily, there are **other** kinds of **GPS** trackers that don’t need phone coverage to work, as **they deliver positioning information using satellites**. Two of the most know devices are **SPOT** and **InReach,** and each one has it’s own data protocol. ### Panamá Adventure Race, a great orographic challenge One of the last races in which Tracktherace was hired to be used was [**AR Panamá 2022**](https://arpanama.com/en/homepage-english/). Panamá is one o the best destinations for an adventure race. It has all the ingredients that any adventurer looks for: Volcanoes, jungle, mangroves, mountains, beaches… Unfortunately, this breathtaking landscape came with a price with respect to the race organization. In this race area, **the phone network coverage was poor**, so the organization opted to ask for the use of Satellite devices. It was needed that Tracktherace implemented that devices protocol on their server-side. But instead of that, **a more agile solution was done**. They used a **YepCode process** **to fetch the information from SPOT servers** (it provides an XML as positioning information). Then they convert that information into the same protocol that Tracktherace had already implemented, and then **forward that information to Tracktherace servers**. In this integration, they only needed to **use the** [**Axios integration**](/docs/integrations/axios) **and XML libraries**. Afterward, a [**scheduled run setup**](/docs/executions/scheduled) was enough to come full circle. Tracktherace joins to other Saas companies like [**Docuten**](https://yepcode.io/using-yepcode/docuten-extended-saas-features-using-yepcode/), that are **validating new features** in a simple approach As a result, they will be able to improve their core business with minimal effort. Happy coding! 🧑‍💻 # Using YepCode to collect and visualize strategic data from your e-commerce > This is an example showing how YepCode may be used to retrieve information from a MySQL database and expose that info in a HTTP endpoint with JSON format. As seen before, [**YepCode can be used for tedious ETL tasks**](https://yepcode.io/using-yepcode/how-to-automate-efficiently-data-movements-from-google-bigquery-to-snowflake/) that can be time-consuming to perform. Just simply using its automation potential. From the point of view that we can offer as its creators, we believe that the potential of Yepcode is enormous. And **capable of dealing with very complex processes that involve the treatment of large volumes of data,** in a very efficient way. Today, we are happy to tell you **how to retrieve, filter and extract your most important e-commerce data.** This can help you improve your business and save time configuring servers, tools or scripts. ### So, let’s code! This example shows how we can use [**#YepCode**](https://twitter.com/hashtag/YepCode?src=hashtag_click) to retrieve information from a **MySQL** database of an online store built with **Woocommerce** and expose that information to a **JSON-formatted HTTP endpoint.** The first step to get the most out of your e-commerce data is to create a credential that stores the information to access the MySQL **database by giving access to them from YepCode cloud.** We’ll use the [**YepCode tunneling system**](/docs/network-access), which allows using SSH tunnels to connect to services behind a firewall. Next, we’ll create a new process accepting the product name filter as a parameter. We’ll use promises to ensure that the result is returned after every needed work has been done. Then we’ll add the process source **code** to: * Open the database **connection** * Run the **query** with the filter as param * Close **connection** * And return the **results** As we want to expose that information in an HTTP **endpoint,** we’ll create a new **Webhook** **Trigger** that will generate a **cURL** sample to run the Webhook from a terminal. We’ll run a synchronous execution to retrieve and show the final result. Remember that our [**Docs platform**](/docs/) includes every single detail to make the most out of YepCode, You can watch this process in the next video! Happy coding! # How to efficiently automate bulk data movement from Google BigQuery to Snowflake > We show you how YepCode can be used to automate the movement of large amounts of data from BigQuery to Snowflake in an incremental approach. Following the topic line of articles in which we explained in detail some practical examples of [**how to carry out different processes, automation and integrations with YepCode**](https://yepcode.io/blog/), today we are going to talk about how to automate the transfer of large volumes of data from **Google BigQuery to Snowflake** in the most efficient way. ### Moving large amounts of data from Google BigQuery to Snowflake is not an agile duty There are lots of **NoCode ETL tools** in the market that **allow moving information between several data sources** (both on-premise services or SaaS). But it’s a common problem that users can’t fully adapt those loading processes to all their needs. Think, for example, in a scenario where information is generated every day in [**Google BigQuery**](/docs/integrations/google-bigquery) (ie: Google Analytics events information). Imagine that you want to **copy that information into a** [**Snowflake**](/docs/integrations/snowflake/) **database in a nightly process**. A mandatory requirement should be to copy only new events that have not been previously copied. Before going to BigQuery, you need to go to **Snowflake to retrieve the last loaded date**. This way you can use it later **to build the BigQuery SQL sentence**. Typically, this may be to **check the max value of a date** column or use a control table that **tracks every load execution**. You may also need to be notified (with an [**email**](/docs/integrations/nodemailer/) or a [**Slack**](/docs/integrations/slack-bolt/) notification) about **how that load was performed** (ie: reporting the number of new events loaded). One last requirement could be take to into account that **millions of events are generated every day**. In that case, a *simple* approach of \*\*running an SQL against BigQuery and for each row performing an insert in Snowflake may not work.\*\*‍ ```js // This is a bad approach to load millions of rows const [job] = await bigqueryClient.createQueryJob({    query: `SELECT column1, column2 FROM table1` }); const [rows] = await job.getQueryResults(); snowflakeClient.execute({    sqlText: 'insert into table1(column1, column2) values(?, ?, ?)',    binds: rows.map((row)=> [row.column1, row.column2]]) }); ``` ### We leverage Yepcode integrations to create the most effective workflow for this process Under this situation, the flow we would propose using YepCode integrations would include these steps: * Run a **synchronous SQL** **select against Snowflake** to get the last loaded date and also the current amount of events. We could **use a reusable function for this syncExec approach** and **include it in one** [**YepCode JS Module**](/docs/processes/js-modules): ```js exports.snowflakeSyncExec = (snowflakeClient, sqlText, binds = [], rest = {}) => {  return new Promise((resolve, reject) => {    snowflakeClient.execute({      sqlText,      binds,      ...rest,      complete: (err, stmt, rows) => {        if (err) {          reject(err);          return;        }        resolve([stmt, rows]);      },    });  }); } ``` * With that **reusable function**, the last loaded **date** and current amount of **rows** could be **retrieved** with something like: ```js const [, rows] = await snowflakeSyncExec(snowflakeClient, "SELECT MAX(DATE) AS LAST_LOADED_DATE, COUNT(1) AS ROWS_AMOUNT FROM table1"); const LAST_LOADED_DATE = rows[0].LAST_LOADED_DATE const ROWS_AMOUNT = rows[0].ROWS_AMOUNT ``` * Using the previously retrieved date, we could **create a Google BigQuery SQL sentence** to get the new events and **execute** that query **in BigQuery**. * Instead of returning the rows, we’ll **leave them in a** [**Google Cloud Bucket**](/docs/integrations/google-storage/) **with CSV format**. * To achieve this, we must **use the export data feature**, which may **leave the rows returned by the query in a CSV** file within Google Cloud Bucket [(](https://cloud.google.com/bigquery/docs/exporting-data)[related docs)](https://cloud.google.com/bigquery/docs/exporting-data). * A piece of sample code could be: ```js const exportQuery =  `EXPORT DATA OPTIONS(  uri='gs://my-google-cloud-bucket-name/my-table-export-file_*',  format='CSV',  header=true,  compression='GZIP',  field_delimiter=',') AS  SELECT column1, column2 FROM table1 WHERE date > @last_loaded_date  `; googleBigQueryClient.createQueryJob({  query: exportQuery,  params: {last_loaded_date: LAST_LOADED_DATE} }); ``` * Note that this **data export** approach may be **also used with GZIP compression** to reduce network use. * Having the query result exported in a file in the bucket, we can directly **load that CSV file into Snowflake** **using** a preconfigured stage. This is a **lovely feature** in Snowflake ([related docs](https://docs.snowflake.com/en/user-guide/data-load-gcs-copy.html)). * The piece of code could be: ```js const importCSVSqlSentence =  `COPY INTO my_table_name  FROM @stage_for_google_cloud_bucket  PATTERN='my-table-export-file_.*';`; snowflakeSyncExec(snowflakeClient, importCSVSqlSentence); ``` * Having the new information loaded in Snowflake, we could **remove the previously generaded CSV files**. The [**Google Cloud Storage**](/docs/integrations/google-storage/) integration may help us: ```js googleCloudStorageClient.bucket('my-google-cloud-bucket-name').deleteFiles({    prefix: 'my-table-export-file_' }); ``` * As last step we could **run another query in Snowflake** to get the new number of events loaded and with that information, we could **build a notification message** and deliver it via email or with the slack integration [(related docs)](https://slack.dev/bolt-js/concepts#message-sending). * The piece of code to send that message could be: ```js await slackBotClient.chat.postMessage({  channel: "bigQuery-snowflake-load",  text: `Load successfully finished with ${rowsAmount} new rows copied!`, }); ``` To implement the full process in YepCode, you’ll need to **configure a Google service account** with access to the **Google BigQuery** and **Google Cloud Bucket**. Also, follow the guide in Snowflake to configure a stage that may be able to read information from that Bucket.Having that configuration created, the best option could be to **create a generic process** that could **carry out the movement of information** in a parameterized way, receiving these parameters: * SQL sentence to execute in Google BigQuery (having the start load date as a parameter) * SQL sentence to execute in Snowflake to retrieve the last loaded date and the number of events * Snowflake destination database and table name ![YepCode imput parameters to automate bulk data movement](/_astro/63318400fa4ab1baf8070720_Screenshot-2022-01-20-at-15.05.25.aA8sM25I_2bIWW7.webp) # Using YepCode to publish a Snowflake query result into Airtable > We move information between Snowflake and Airtable by creating a process that executes an SQL query in Snowflake and streams the results to Airtable. [**Airtable**](https://www.airtable.com/) and [**Snowflake**](https://www.snowflake.com/) are two of the big players in the modern \*\*databases ecosystem.\*\*‍ Their approach is quite different. **Snowflake** focus on **data warehouse** features **allowing the management of enormous amounts of information** in a faster and more flexible way than traditional databases. **Airtable**, on the other hand, is more similar to Excel on steroids, **allowing to build powerful applications with a NoCode approach**. ### How can I move data from Snowflake to Airtable with YepCode? In this post we’ll show how **YepCode** may be **used to move information between these two SaaS**, creatinga generic process that receives the following input **parameters**: * The Snowflake query to be executed * The Airtable base & view names * The (optional) mapping between Snowflake and Airtable column names * A flag to decide if use streams instead of loading all query results in memory (more suitable for a great number of rows) The process will start by **opening the connection** to Snowflake. Then it will **run the query in an asynchronous way** (using JS promises). When the query **returns all the rows** (or for each row in the streamed approach), **it will create new entries in Airtable** using the correct column mapping. ### **Ok, but too much text, show me code!** In this case, **we are not doing a *copy\&paste*** of the full process code (as we have done in one previous post for [**Cryptocurrency dollar-cost averaging sample**](/blog/cryptocurrency-dollar-cost-averaging-using-yepcode/). Here, we only reference a public view of the process. From that public page, you couldn’t run the sample, but you only have to [**create your own YepCode account**](https://yepcode.io/get-started/) and create the needed [**Airtable**](/docs/integrations/airtable) **and** [**Snowflake**](/docs/integrations/snowflake) credentials to start to use it! Happy coding 🧑‍💻[](https://cloud.yepcode.io/public/sandbox/processes/sample-snowflake-query-to-airtable-base) [Click here to view the process in full detail](https://cloud.yepcode.io/public/sandbox/processes/sample-snowflake-query-to-airtable-base) # How Docuten has extended their Saas features using YepCode > Docuten offers its clients invoices in various electronic formats not included in its core. The YepCode process connects to the Docuten FTP server using our SFTP integration. [**Docuten**](https://docuten.com) is a leader in **administrative processes digitalization**, transforming clients into “paperless companies”. They achieve that by digitally converting any administrative processes through **digital signature, electronic invoicing and payments**. By relying on **Docuten** as their sole provider, companies can **reduce costs** by 50%. In addition, they can perform this deployment 2.5 times faster than working with several different providers. ‍**Docuten has recently started to use YepCode**. Their main goal is to validate some new functionalities before including them in their core **Saas product**. Here is a good example of how they are doing this. There is a **YepCode process** that allows Docuten to offer their clients to **receive invoices in several electronic invoice formats that are not yet in their core product**. Their platform works mainly with factura-e invoice format. And they may place the generated invoices in an **FTP server.** The created YepCode process **opens a connection to that FTP server,** looking for some newly generated invoices. This connection is possible thanks to the use of our [**SFTP integration**](/docs/integrations/sftp). If any new invoices appear on the server, they are converted to another invoice format using an [**XML parser**](/docs/libraries/fast-xml-parser). After that, the **new documents are uploaded again to the FTP server**. With this simple process, Docuten is able to offer **several electronic invoice formats to their clients.** These formats may be extended by publishing [**new versions of the YepCode process.**](/docs/processes/process-versioning) Additionally, this process hasn’t modified their core product at all. In conclusion, we believe that using **YepCode** with this strategy can **help many Saas companies to validate new features.** As a result, they will be able to improve their core business **with minimal effort.** [**Book a demo**](https://yepcode.io/book-a-demo/) if you think that YepCode may help you and we’ll be happy to guide you to get the most out of it. # Cryptocurrency dollar cost averaging using YepCode > YepCode could help you to do cryptocurrency dollar cost averaging (DCA) investment with using the Kraken, Binance and Coinbase exchanges. ## The word cryptocurrency is no longer just a fad. For many, the **cryptocurrency universe** is just a hobby, but for many others a way to invest their money. In this article, we are going to show you how [YepCode could help you](/blog/why-was-yepcode-created/) to do **dollar-cost averaging (DCA)** investments with cryptocurrencies using the **Kraken exchange**. Dollar-cost averaging is an **investment strategy** that aims to **reduce the impact of volatility on large purchases of financial assets**. And, for sure, those cryptocurrencies are volatile 💸. The idea behind DCA is to **spread purchases across predefined intervals, regardless of asset prices**. You can find lots of information about this strategy ([Wikipedia](https://en.wikipedia.org/wiki/Dollar_cost_averaging), [CoinMarketCap article](https://coinmarketcap.com/alexandria/article/what-is-dollar-cost-averaging)…), or use some tool like [dcaBTC](https://dcabtc.com/) to calculate how this strategy could work with [Bitcoin](https://en.wikipedia.org/wiki/Bitcoin) in the past. ## Strategy is the key to improving your activity with cryptocurrencies Think that **you want to invest in Bitcoin** and your budget is $500. You could make an **order at today’s price**. But maybe **you don’t want to invest the whole budget taking the risk that tomorrow the price is lower.** An alternative could be to invest that budget in a fixed period of 5 months, investing $100 a month or $25 a week or $3,33 a day. If you want **to do this with manual orders in your cryptocurrency exchange, it may be a hard task**. The biggest problem may be that you forgot to do the orders. Or your sentiment about the price at that moment could make that you don’t really create the orders, going against the strategy. A much better approach would be to **automate that order creation tasks, and YepCode is a perfect tool to do that.** This blog post shows how to create a flexible YepCode process that allows you to do DCA for customers of the popular crypto exchange [Kraken](https://www.kraken.com/), using its [Rest API](https://docs.kraken.com/rest/). The process accepts the following **parameters** for each execution: * Cash currency symbols to be used: **EUR**, **USD**, **GBP**, **JPY**,… (the process doesn’t make deposits from banks, so the customer must have enough balance for the order in its **Kraken** account) * **Cryptocurrency** **symbols** to buy: **BTC**, **ETH**, **ADA**,… * Amount of cash to buy at the current **crypto price** * An array of other possible orders at a reduced price (percentage/amount). If your purpose is to learn **how a process can be created in YepCode from scratch**, keep reading as we are showing the steps and linking to the related page in [our docs](/docs/). ## So let’s stop talking and go for it. The first step is to create a [new process](/docs/processes/): ![](/_astro/633183ff3d96495aaa65e757_create-new-process.B3sl6zBf_Z227Dq7.webp) YepCode supports a [README](/docs/processes/the-readme) for each process. For our case, it could be interesting to add some guides about what changes we need in Kraken to allow the process to access your cryptocurrency account. The README content is a [markdown](https://en.wikipedia.org/wiki/Markdown), and a proposal content could be: ```js # Crypto DCA on Kraken This is a YepCode process to implement [dollar cost averaging (DCA)](https://en.wikipedia.org/wiki/Dollar_cost_averaging) investment with cryptocurrencies on [Kraken](https://www.kraken.com/) exchange using its [REST API](https://docs.kraken.com/rest/). In orther to use this YepCode process, you have to be customer of Kraken, and you have to create one pair of API keys. ## Kraken API keys creation You can do this with the following steps: * Login to your Kraken account. * Visit *Security / API* under user menu. * Press *Add key* and set the following permissions:  * Funds:    * Query Funds  * Order & Trades:    * Query Open Orders & Trades    * Query Closed Orders & Trades    * Create & Modify Orders    * Cancel/Close Orders * Press *Generate Key* and backup your new API keys More info in [Kraken help](https://support.kraken.com/hc/en-us/articles/360000919966-How-to-generate-an-API-key-pair-) ``` Following this guide, and after having these two keys, we have to create two [YepCode environment variables](/docs/processes/team-variables/) to store their values. The name of the variables should be **KRAKEN\_API\_KEY** and **KRAKEN\_API\_SECRET**. It’s time to configure the [input params](/docs/processes/input-params/) for the process, allowing the user to provide the cash and cryptocurrencies, to use. And also the amount of cash to spend. The JSON to configure our input parameterss would be this one: ```js {  "type": "object",  "title": "DCA orders configuration",  "properties": {    "cashCurrencyCode": {      "title": "The cash currency code with available amount on Kraken account",      "description": "Valid values: USD, EUR, CAD, JPY, GBP, CHF, AUD",      "type": "string"    },    "cryptoCurrencyCode": {      "title": "The crypto currency to buy",      "description": "Valid values: BTC, ETH, ADA, BNB, SOL, DOT,...",      "type": "string"    },    "closeOpenOrdersForThisCrypto": {      "title": "Close open orders for this currency pair?",      "type": "boolean"    },    "marketOrderQuantity": {      "title": "Amount of cashCurrencyCode to invest at current price",      "description": "If some quantity is set, a market price order will be created",      "type": "number",      "default": 0    },    "ordersBelowCurrentPrice": {      "title": "Other orders for lower price",      "description": "Process allow to create orders for a reduced market price (in percentage)",      "type": "array",      "items": {        "type": "object",        "properties": {          "pricePercentage": {            "title": "The percentage (0.01-0.99) of the current price to place this order",            "description": "If you set 0.85, and current price is 300, the order would be created for 255",            "type": "number",            "default": 0,            "min": 0.01,            "max": 0.99          },          "quantity": {            "title": "Amount of cashCurrencyCode to invest at this percentage",            "type": "number",            "default": 0          }        }      }    }  },  "required": [    "cashCurrencyCode",    "cryptoCurrencyCode"  ] } ``` As a result, **YepCode could build a form** to be shown to the user on each new execution configuration: ![](/_astro/633183ff3d9649373065e75b_input-params-960x1024.Dp2f8mcL_Z2Qk6.webp) We’ll need all the code to **interact with Kraken API**. We could add all the implementation in this same process. But as it seems a quite reusable component, a better idea is to use the [YepCode JS modules](/docs/processes/js-modules/) feature to create a new module with a Kraken API client implementation. Let’s create a new Library: ![](/_astro/633183ff3d9649353565e754_create-new-library.BDoFPSVB_1B8Rxw.webp) And **fill the source code for the module**, ensuring that we export the desired objects or functions: ```js // JS module copied, with some minor changes, from: // https://github.com/nothingisdead/npm-kraken-api/blob/master/kraken.js const { post } = require("axios"); const { createHash, createHmac } = require("crypto"); const { stringify } = require("query-string"); // Public/Private method names const methods = {    public: [        "Time",        "Assets",        "AssetPairs",        "Ticker",        "Depth",        "Trades",        "Spread",        "OHLC",    ],    private: [        "Balance",        "TradeBalance",        "OpenOrders",        "ClosedOrders",        "QueryOrders",        "TradesHistory",        "QueryTrades",        "OpenPositions",        "Ledgers",        "QueryLedgers",        "TradeVolume",        "AddOrder",        "CancelOrder",        "DepositMethods",        "DepositAddresses",        "DepositStatus",        "WithdrawInfo",        "Withdraw",        "WithdrawStatus",        "WithdrawCancel",        "GetWebSocketsToken",    ], }; // Default options const defaults = {    url: "https://api.kraken.com",    version: 0,    timeout: 5000, }; // Create a signature for a request const getMessageSignature = (path, request, secret, nonce) => {    const message = stringify(request);    const secret_buffer = new Buffer.from(secret, "base64");    const hash = new createHash("sha256");    const hmac = new createHmac("sha512", secret_buffer);    const hash_digest = hash.update(nonce + message).digest("binary");    const hmac_digest = hmac        .update(path + hash_digest, "binary")        .digest("base64");    return hmac_digest; }; // Send an API request const rawRequest = async (url, headers, data, timeout) => {    // Set custom User-Agent string    headers["User-Agent"] = "Kraken Javascript API Client";    const options = { headers, timeout };    const { data: response } = await post(        url,        stringify(data),        options    );    if (response.error && response.error.length) {        const error = response.error            .filter((e) => e.startsWith("E"))            .map((e) => e.substr(1));        if (!error.length) {            throw new Error("Kraken API returned an unknown error");        }        throw new Error(error.join(", "));    }    return response; }; /** * KrakenClient connects to the Kraken.com API * @param {String}        key               API Key * @param {String}        secret            API Secret * @param {String|Object} [options={}]      Additional options. If a string is passed, will default to just setting `options.otp`. * @param {String}        [options.otp]     Two-factor password (optional) (also, doesn't work) * @param {Number}        [options.timeout] Maximum timeout (in milliseconds) for all API-calls (passed to `request`) */ class KrakenClient {    constructor(key, secret, options) {        // Allow passing the OTP as the third argument for backwards compatibility        if (typeof options === "string") {            options = { otp: options };        }        this.config = Object.assign({ key, secret }, defaults, options);    }    /**     * This method makes a public or private API request.     * @param  {String}   method   The API method (public or private)     * @param  {Object}   params   Arguments to pass to the api call     * @param  {Function} callback A callback function to be executed when the request is complete     * @return {Object}            The request object     */    api(method, params, callback) {        // Default params to empty object        if (typeof params === "function") {            callback = params;            params = {};        }        if (methods.public.includes(method)) {            return this.publicMethod(method, params, callback);        } else if (methods.private.includes(method)) {            return this.privateMethod(method, params, callback);        } else {            throw new Error(method + " is not a valid API method.");        }    }    /**     * This method makes a public API request.     * @param  {String}   method   The API method (public or private)     * @param  {Object}   params   Arguments to pass to the api call     * @param  {Function} callback A callback function to be executed when the request is complete     * @return {Object}            The request object     */    publicMethod(method, params, callback) {        params = params || {};        // Default params to empty object        if (typeof params === "function") {            callback = params;            params = {};        }        const path = "/" + this.config.version + "/public/" + method;        const url = this.config.url + path;        const response = rawRequest(url, {}, params, this.config.timeout);        if (typeof callback === "function") {            response                .then((result) => callback(null, result))                .catch((error) => callback(error, null));        }        return response;    }    /**     * This method makes a private API request.     * @param  {String}   method   The API method (public or private)     * @param  {Object}   params   Arguments to pass to the api call     * @param  {Function} callback A callback function to be executed when the request is complete     * @return {Object}            The request object     */    privateMethod(method, params, callback) {        params = params || {};        // Default params to empty object        if (typeof params === "function") {            callback = params;            params = {};        }        const path = "/" + this.config.version + "/private/" + method;        const url = this.config.url + path;        if (!params.nonce) {            params.nonce = new Date() * 1000; // spoof microsecond        }        if (this.config.otp !== undefined) {            params.otp = this.config.otp;        }        const signature = getMessageSignature(            path,            params,            this.config.secret,            params.nonce        );        const headers = {            "API-Key": this.config.key,            "API-Sign": signature,        };        const response = rawRequest(url, headers, params, this.config.timeout);        if (typeof callback === "function") {            response                .then((result) => callback(null, result))                .catch((error) => callback(error, null));        }        return response;    } } module.exports = KrakenClient; ``` **We like to follow the clean code conventions**. Another interesting module to be created could be one to use **Kraken API** common functions: ![](/_astro/633183ff3d96492b5e65e75c_helper-methods-library-1024x687.OAlAZx67_QLCKP.webp) The full source code of this library would be: ```js module.exports.getAltName = (cashCurrencyCode, cryptoCurrencyCode) => {    return (cryptoCurrencyCode == 'BTC' ? 'XBT' : cryptoCurrencyCode) + cashCurrencyCode; } module.exports.getCurrencyAssetPairsByAltName = async (kraken) => {    const query = await kraken.api("AssetPairs");    const assetPairsByAltName = {};    for (const tradingPair in query.result) {        const altname = query.result[tradingPair].altname;        assetPairsByAltName[altname] = {            tradingPair,            orderMin: parseFloat(query.result[tradingPair].ordermin),        };    }    return assetPairsByAltName; } const cashCurrencyToAssetCode = (cashCurrencyCode) => {    return "Z" + cashCurrencyCode; }; module.exports.getBalance = async (kraken, cashCurrencyCode) => {    const query = await kraken.api("Balance");    return query.result[cashCurrencyToAssetCode(cashCurrencyCode)]; } module.exports.getOpenOrders = async (kraken) => {    const query = await kraken.api("OpenOrders");    return query.result["open"]; } module.exports.closeOrder = async (kraken, orderId) => {    return kraken.api("CancelOrder", { txid: orderId }); } module.exports.getCurrentPrice = async (kraken, pair) => {    const query = await kraken.api("Ticker", { pair });    return query.result[pair]["b"][0]; } module.exports.addOrder = async (kraken, pair, price, volume) => {    const newOrderParams = {        pair,        type: "buy",        ordertype: "limit",        price,        volume,    };    //console.log(`New order params: ${JSON.stringify(newOrderParams)}`);    return kraken.api("AddOrder", newOrderParams); } ``` ‍**The process sends a report using an email client**. In this case, we are using the [Nodemailer](/docs/integrations/nodemailer/) integration to deliver the email using a Gmail account. The integration configuration would be: ![](/_astro/633184003d96493b3365e75d_nodemailer-credentials-810x1024.LSUrW_aB_Z1FRzfN.webp) The last step is to **provide the** [**full source code**](/docs/processes/source-code/) that reads the input params. By using the created modules and the configured mail integration makes the full process. This source code would be: This code example uses deprecated credentials: ```js const mailClient = yepcode.integration.nodemailer('gmail-account') ``` Follow this [guide](/docs/credentials-migration-guide) to migrate your credentials. ```js const {    context: { parameters }, } = yepcode; const KrakenClient = yepcode.import('kraken-api-client'); const krakenHelper = yepcode.import('kraken-api-helper-methods'); const kraken = new KrakenClient(yepcode.env.KRAKEN_API_KEY, yepcode.env.KRAKEN_API_SECRET); const validCashCurrencyCodes = ['USD', 'EUR', 'CAD', 'JPY', 'GBP', 'CHF', 'AUD']; if (!validCashCurrencyCodes.includes(parameters.cashCurrencyCode)) {    console.error(`Invalid cashCurrencyCode ${parameters.cashCurrencyCode}. Valid values are ${validCashCurrencyCodes}`);    return; } const cashBalance = await krakenHelper.getBalance(kraken, parameters.cashCurrencyCode); if (!cashBalance) {    console.error(`No available balance in ${parameters.cashCurrencyCode}`);    return; } console.log(`Current balance in ${parameters.cashCurrencyCode} is ${cashBalance}`); const assetPairsByAltName = await krakenHelper.getCurrencyAssetPairsByAltName(kraken); const altName = krakenHelper.getAltName(parameters.cashCurrencyCode, parameters.cryptoCurrencyCode); const assetPair = assetPairsByAltName[altName]; if (!assetPair) {    console.error(`No assetPair found for alt name ${altName}. Available values are ${JSON.stringify(assetPairsByAltName)}`);    return; } const { tradingPair, orderMin } = assetPair; console.log(`Trading pair to be used is ${tradingPair}`); console.log(`Minimum order volume is ${orderMin}`); let openOrdersRemovedAmount = 0; if (parameters.closeOpenOrdersForThisCrypto) {    const openOrdersById = await krakenHelper.getOpenOrders(kraken);    console.log(`There already are ${Object.keys(openOrdersById).length} opened orders`);    for (const orderId in openOrdersById) {        const order = openOrdersById[orderId];        if (order.descr.pair == tradingPair) {            console.log(`Found order of pair ${tradingPair} to be closed: ${orderId}`);            const queryCancel = await krakenHelper.closeOrder(kraken, orderId);            console.log(`Order closed ${queryCancel}`);            openOrdersRemovedAmount++;        }    } } const currentPrice = await krakenHelper.getCurrentPrice(kraken, tradingPair); console.log(`Current price of ${parameters.cryptoCurrencyCode} is ${currentPrice}${parameters.cashCurrencyCode}`); const currentPriceAmountOfDecimals = currentPrice.toString().split(".")[1].length || 0; let ordersToCreate = []; if (parameters.marketOrderQuantity && parameters.marketOrderQuantity > 0) {    ordersToCreate.push({        pricePercentage: 1,        quantity: parameters.marketOrderQuantity    }) } if (parameters.ordersBelowCurrentPrice) {    ordersToCreate = ordersToCreate.concat(parameters.ordersBelowCurrentPrice); } const createdOrders = []; console.log(`Creating ${ordersToCreate.length} orders`); for (const [i, order] of ordersToCreate.entries()) {    const { pricePercentage, quantity } = order;    if (pricePercentage < 0.01 || pricePercentage > 1) {        console.error(`Order ${i + 1} not created. Percentage must be in range 0.01 - 1`);        continue;    }    const putBid = parseFloat((currentPrice * pricePercentage).toFixed(currentPriceAmountOfDecimals));    const volume = quantity / putBid;    if (volume < orderMin) {        console.error(`Order ${i + 1} not created. Volume must be higher than ${orderMin} (attempt to use ${volume})`);        continue;    }    const totalCost = volume * putBid;    console.log(`Order ${i + 1} - Total cost ${totalCost}${parameters.cashCurrencyCode} / Price ${putBid}${parameters.cashCurrencyCode} / Amount ${volume}${parameters.cryptoCurrencyCode}`);    const newOrder = await krakenHelper.addOrder(kraken, tradingPair, putBid, volume);    const description = newOrder.result.descr.order;    const transactionId = newOrder.result.txid;    console.log(`New order created with id ${transactionId} (${description}))`);    createdOrders.push({        transactionId,        totalCost,        price: putBid,        volume    }) } const mailHtmlContent = `

Your Kraken balance in ${parameters.cashCurrencyCode} is ${cashBalance}.

Current price of ${parameters.cryptoCurrencyCode} is ${currentPrice}.

${(openOrdersRemovedAmount > 0 ? `

${openOrdersRemovedAmount} opened order for ${tradingPair} already existed, and have been removed.

` : '')}

${ordersToCreate.length} new orders have been created:

       ${createdOrders.map(({ transactionId, totalCost, price, volume }) => {            return `                                                                            `;        }).join('')}    
Order id Total cost in ${parameters.cashCurrencyCode} Price in ${parameters.cryptoCurrencyCode} Amount in ${parameters.cryptoCurrencyCode}
${transactionId}${totalCost}${price}${volume}
` const mailClient = yepcode.integration.nodemailer('gmail-account') await mailClient.sendMail({    from: "YepCode ",    to: "cryptobuyer@gmail.com",    subject: `YepCode DCA Bot   - New orders for crypto ${parameters.cryptoCurrencyCode}`,    html: mailHtmlContent }) console.log("Report email sent"); ``` Having all this setup created, we could start a new on [demand execution](/docs/executions/on-demand/) of the process, **providing the requested parameters**: ![](/_astro/633183ff3d9649fc2b65e755_new-execution-params.UdvKYzPf_NkxnD.webp) And navigation to the [process execution details](/docs/executions/), we could also see the log output and execution information: ![](/_astro/633183ff3d9649003565e75a_execution-log-trace-1024x694.B--NPkJ2_Z2f7vcw.webp) The used code is generating an email report, and the result for this execution is this one: ![](/_astro/633183ff3d96492e7465e758_mail-report.kqbAI92c_ZLn4lg.webp) After being sure that everything works ok, and **having done some on-demand executions**, it’s time to create a [scheduled execution](/docs/executions/scheduled/) configuration to take the most of DCA. Let’s create a new periodic execution on Friday’s morning: ![](/_astro/633183ff3d96493eb465e759_DCA-schedule-config-1.BKETf-MV_Z1jaIEr.webp) With the purpose of **buying 10€ of ETH**: ![](/_astro/633183ff3d96493a0765e756_DCA-schedule-config-2.D32rpN2w_Z2ii9cL.webp) And that’s all! With this post, we hope to have shown you **all the power that YepCode has** to solve your everyday programming problems. # Why was YepCode created? > YepCode is designed to help connect entire software applications together, allowing you to solve development problems in a very agile and productive way. ### Find out the history of YepCode and why we are going against the NoCode stream. In this article, we are going to explain to you the reason why we created YepCode. Are you ready? Well, if you’ve made it this far, **Zapier, IFTTT, or Tray are probably familiar to you**. Don’t get us wrong. T**hey are** **excellent NoCode automation tools.** But they are just that, tools for the layman. Very nice and easy to use, **but with limitations**. We have no doubt that, **if you know how to use code, you can be much more productive** and go one step further in your daily work. Our team is made of software craftsmen and **YepCode is the result of our passion for writing source code**. We believe that this does not have to go against the aim of being agile and **getting our tasks done in a short time**. That is why YepCode is our manifest. **Yep (Yes) + Code. We say yes to the code** and we defend everything it represents: craftsmanship, pampering, versatility, scalability, potential, quality. ### You know what it means, but … how did YepCode come about? We think that **the idea of automating tasks by writing scripts** that would replace many manual workflows and interventions that were documented in a wiki, **is a huge win in any company.** This allows to **drastically reduce human errors,** being able to **schedule and monitor tasks** instead of having one user with access to the systems infrastructure doing the changes. We are big fans of solving problems with tools like Zapier, n8n or even Amazon Lambda, but we don’t like some of the limits that each one has. With the full NoCode tools, **we may end in a mess when the problem to solve grows**, and the technical requirements are more complex. The Amazon Lambda, doesn’t have this problem but it’s **very tied to Amazon services** infrastructure. So we decided to leave the developer all the flexibility to create processes, and We **chose one of our favourite programming languages (JavaScript)** as base for this new platform. This allowed us to **achieve integrations** without the need to look for the best package. Without having to worry about where to **store the credentials** and being able to **monitor each execution**. And we created all this within a robust multitenant solution that **any client could use.** ### And all this, really of what use can it be? We really think that **a platform that helps you solve the slow workflow** that occurs when starting a project from scratch, with source code repositories, environments, deployments, compilations, etc, is a very **useful tool**. YepCode can help you [**to solve many kinds of problems in a very effective way**](https://yepcode.io/)**.** Tasks like streaming information from a [**MongoDb database**](/docs/integrations/mongodb/), merging it with more information retrieved from a [**GraphQL service**](/docs/integrations/graphql/), publishing each merged record to an [**MQ queue**](/docs/integrations/amqp/) and creating a **PDF file** that is then sent via email, are the **daily work of YepCode**. We designed YepCode to **help connect entire software applications together.** Moving information between them, processing flows, chaining events, performing periodic tasks and reporting. Without a doubt, **a great tool for code lovers**.