Aller au contenu

Workflow Step Type

Ce contenu n’est pas encore disponible dans votre langue.

Translate in Crowdin

This module allows you to create custom workflow step types to extend the default list of workflow steps in Crowdin Enterprise. With this app installed, the new workflow step types become available in the workflow editor, where they can be added to workflows and templates, enabling greater customization and flexibility.

A custom workflow step acts as an external processing stage in a workflow: Crowdin Enterprise handles the routing of strings, status tracking, and progress counters, while your app implements the step’s condition of done – the custom logic that decides when a string is considered complete on the step and which output it leaves through. Typical use cases include AI-based review, integration with an external review or MT system, compliance gates, or delay/scheduling steps.

The Workflow Step Type module follows an asynchronous, event-driven integration model:

  1. An organization admin installs the app. The custom step types provided by the app become available in the workflow editor.
  2. A project manager adds the custom step to a workflow or workflow template and configures it via the settings UI provided by the app.
  3. When strings reach the custom step, Crowdin Enterprise sends the string.status_on_step.recalculation_triggered webhook event to the app.
  4. The app evaluates its condition of done for the received strings. Processing is asynchronous and can take as long as needed.
  5. The app updates the status of each processed string via the API, assigning it to one of the step’s declared output ports according to its routing logic.
  6. Crowdin Enterprise routes the strings to the next workflow step connected to that output.

Apps that include the workflow-step-type module must meet all of the following requirements. An app descriptor that doesn’t meet them will fail validation during installation:

  • crowdin_agent authentication – the app must use the crowdin_agent authentication type and declare an agent in the app descriptor. Other authentication types (e.g., crowdin_app or none) are not allowed for this module. Read more about Authentication.
  • Companion Webhook module – the same app must also declare a Webhook module subscribed to the string.status_on_step.recalculation_triggered event. Without it, the custom step cannot receive strings for processing.
  • App backend – all module URLs are relative to the app’s baseUrl, so the module is not compatible with serverless apps.
  • Crowdin Enterprise only – custom workflow steps are available only in Crowdin Enterprise projects with workflows.

The workflow-step-type module requires the crowdin_agent authentication type. If the app descriptor uses any other authentication type (or omits the authentication object), the installation fails with the following error:

Only crowdin_agent authentication type is allowed for workflow-step-type module type

A custom workflow step is a long-lived participant in your projects rather than a UI extension. It processes strings asynchronously, triggered by webhooks, without any user session involved. To support this, Crowdin Enterprise creates a dedicated agent – a bot user that represents your app in the organization:

  • The agent user is created automatically when the app is installed and removed when the app is uninstalled.
  • All API calls the app makes to process strings on the custom step are authenticated as the agent user.
  • The agent must have manager access to every project where the custom step is used. A project manager invites the agent to the project as a manager as part of setting up the workflow step. Alternatively, the agent can be assigned as a manager to all existing projects during the app installation.
  • All actions performed by the app are attributed to the agent user in the project activity, providing a clear audit trail.

When using the crowdin_agent authentication type, the app descriptor must include a top-level agent object that describes the agent user:

manifest.json
{
"authentication": {
"type": "crowdin_agent",
"clientId": "your-client-id"
},
"agent": {
"name": "Custom Step",
"username": "custom-step-agent",
"avatarUrl": "/assets/agent-avatar.png"
}
}
agent.username

Type: string

Required: yes

Description: The username for the agent user created in the organization.

agent.name

Type: string

Required: no

Description: The display name of the agent user. If omitted, the app name is used.

agent.avatarUrl

Type: string

Required: no

Description: The relative URL to the agent user’s avatar. If omitted, the app logo is used.

The token flow for crowdin_agent is similar to the crowdin_app flow. When the app is installed, Crowdin sends the Installed event to the app. For apps with the crowdin_agent authentication type, the Installed event payload additionally contains the agentId property – the numeric identifier of the agent user created for your app.

To obtain an API access token, the app sends the following request:

Terminal window
POST https://accounts.crowdin.com/oauth/token

Token request parameters:

grant_type: crowdin_agent

Type: string

Required: yes

Description: Specifies the token flow for an agent app.

client_id

Type: string

Required: yes

Description: The Client ID for the app is received when the app is registered.

client_secret

Type: string

Required: yes

Description: The Client Secret for the app is received when the app is registered.

app_id

Type: string

Required: yes

Description: Crowdin app identifier from the app descriptor.

app_secret

Type: string

Required: yes

Description: The unique secret used to authorize your Crowdin app. This value is retrieved from the Installed event.

domain

Type: string

Required: yes

Description: The name of the organization the app is installed to. This value is retrieved from the Installed event.

user_id

Type: integer

Required: yes

Description: The identifier of the user who installed the app. This value is retrieved from the Installed event.

agent_id

Type: integer

Required: yes

Description: The identifier of the agent user created for your app. This value is retrieved from the Installed event (agentId property).

The resulting access token is issued for the agent user. Use it in the Authorization: Bearer header for the API methods that manage string statuses on the custom step.

You can grant access to this module to one of the following user categories:

  • Only organization admins
  • All users in the organization projects
  • Selected users

The example below shows a complete app descriptor for an app that provides a custom workflow step. Note the crowdin_agent authentication type, the agent object, and the companion webhook module subscribed to the string.status_on_step.recalculation_triggered event – all three are required:

manifest.json
{
"identifier": "custom-workflow-step-app",
"name": "Custom Workflow Step App",
"description": "A sample app that provides a custom workflow step",
"logo": "/logo.png",
"baseUrl": "https://example.com",
"authentication": {
"type": "crowdin_agent",
"clientId": "your-client-id"
},
"agent": {
"name": "Custom Step",
"username": "custom-step-agent",
"avatarUrl": "/assets/agent-avatar.png"
},
"events": {
"installed": "/hooks/installed"
},
"scopes": [
"project"
],
"modules": {
"workflow-step-type": [
{
"key": "custom-workflow-step",
"name": "Custom Workflow Step",
"logo": "/logo.png",
"description": "A sample custom step for Crowdin Enterprise workflows",
"boundaries": {
"input": {
"title": "Input Strings",
"ports": [
"untranslated",
"translated",
"approved",
"all",
"false",
"true",
"skipped",
"initial"
]
},
"outputs": [
{
"title": "Processed Strings",
"port": "translated"
},
{
"title": "Unprocessed Strings",
"port": "untranslated"
}
]
},
"editorMode": "comfortable",
"updateSettingsUrl": "/settings/custom-workflow-step",
"deleteSettingsUrl": "/delete/custom-workflow-step",
"url": "/workflow-step/custom-workflow-step",
"environments": [
"crowdin-enterprise"
]
}
],
"webhook": [
{
"key": "workflow-step-webhook",
"url": "/hooks/workflow",
"events": [
"string.status_on_step.recalculation_triggered"
]
}
]
}
}
key

Type: string

Required: yes

Description: Module identifier within the Crowdin app.

name

Type: string

Required: yes

Description: The human-readable name of the workflow step type shown in the workflow editor.

logo

Type: string

Required: no

Description: The relative URL to the workflow step type’s logo that will be displayed in the workflow editor.
The recommended resolution is 48x48 pixels.

description

Type: string

Required: no

Description: The human-readable description of what the workflow step does.
The description will be visible in the Crowdin Enterprise UI.

boundaries

Type: object

Required: yes

Description: Defines the input and output ports for the workflow step, determining how strings enter and exit the step. Read more about Boundaries and Ports.

boundaries.input

Type: object

Required: yes

Description: Specifies the properties of the input data for the workflow step, including available ports. Exactly one input group is allowed.

boundaries.input.title

Type: string

Required: yes

Description: The title for the input section of the workflow step (3–30 characters).

boundaries.input.ports

Type: array

Required: yes

Allowed values: untranslated, translated, approved, all, false, true, skipped, initial

Description: Defines the string statuses that can be processed by this workflow step.

boundaries.outputs

Type: array

Required: yes

Description: Specifies the possible outputs of the workflow step, determining how processed strings move forward. A step can declare one or two outputs.

boundaries.outputs.[]

Type: object

Required: yes

Allowed values for port: untranslated, translated, approved, all, false, true, skipped

Description: Defines the outputs of the workflow step. Each object in the array contains:

  • title (string) – The title for the output section of the workflow step (3–30 characters).
  • port (string) – The port type used for connecting outputs. The initial port cannot be used as an output.
editorMode

Type: string

Required: no

Allowed values: side-by-side, comfortable, multilingual

Description: Defines the default Crowdin Enterprise Editor mode used when a user opens the Editor for this workflow step.

updateSettingsUrl

Type: string

Required: no

Description: The relative URL for sending updated workflow step settings after a user saves changes in the workflow editor. Used if the custom workflow step has a configuration.

deleteSettingsUrl

Type: string

Required: no

Description: The relative URL notified when the workflow step is deleted in the workflow editor.

url

Type: string

Required: no

Description: The relative URL to the iframe with the settings UI for the workflow step. The page is loaded in the workflow editor when a user configures the step.

environments

Type: string

Allowed values: crowdin-enterprise

Description: Set of environments where a module could be installed.
This parameter is needed for cross-product applications.

The boundaries object declares the step’s connectors in the workflow graph. Ports describe the state of the content that flows through them, not the steps they connect. An output of one step can be connected to an input of the next step if both use the same port, or if either side uses the all port.

PortMeaning
initialThe string arrived directly from the workflow’s Start point without prior processing. Can be used only as an input.
untranslatedThe string has no translation yet.
translatedThe string has a translation.
approvedThe string’s translation has been approved.
skippedThe string was bypassed by a previous step (e.g., pre-translation found no match).
true / falseA generic boolean pair for branching logic. These are the same connectors used by Custom Code steps.
allA wildcard that can be connected to any port on the other side.

A common configuration is one “success” output (e.g., translated, approved, or true) and one “failure” or “bypass” output (e.g., untranslated, skipped, or false), letting the workflow route processed and unprocessed strings down different paths.

The Workflow Step Type module relies on webhooks and API methods to communicate with Crowdin Enterprise. Apps that include this module must also define the Webhook module to receive string-related events (i.e., string.status_on_step.recalculation_triggered) and process them accordingly.

Crowdin Enterprise sends a batched webhook payload to the app’s Webhook module whenever strings reach a custom workflow step provided by the app. When a string lands on the custom step (e.g., it was just added, moved there by a previous step, or re-triggered), its status on the step becomes Need Process, and the webhook event is queued for delivery.

This payload contains the string.status_on_step.recalculation_triggered event and includes all relevant strings that need external processing (e.g., AI-based proofreading).

Example webhook payload for the string.status_on_step.recalculation_triggered event:

{
"events": [
{
"event": "string.status_on_step.recalculation_triggered",
"stringStatus": {
"status": "NEED_PROCESS",
"output": "",
"originEvent": "string.added",
"organizationId": "200007777",
"translation": {
"id": 1106423,
"identifier": "058eb6ea2bdcc79a6a7208783c8bfb50",
"key": "string_1",
"text": "Not all videos are shown to users. See more",
"type": "text",
"context": "string_1",
"maxLength": "50",
"isHidden": false,
"isDuplicate": false,
"masterStringId": null,
"revision": 1,
"hasPlurals": false,
"labelIds": [],
"url": "https://umbrella.crowdin.com/editor/173/743/en-et#1106423",
"createdAt": "2024-10-29T10:47:13+00:00",
"updatedAt": null,
"file": {
"id": 743,
"name": "umbrella_app.xml",
"title": null,
"type": "android8",
"path": "/umbrella_app.xml",
"status": "active",
"revision": "1",
"branch": {
"id": null
},
"directory": {
"id": null
},
"project": null
},
"project": {
"id": 173,
"userId": 1,
"sourceLanguageId": "en",
"targetLanguageIds": [
"uk",
"et"
],
"identifier": "d3026ae4cff9820bc140a210d23b35ad",
"name": "Project Name",
"createdAt": "2024-10-25T14:37:47+00:00",
"updatedAt": "2024-10-25T14:37:47+00:00",
"lastActivity": "2025-01-30T09:32:58+00:00",
"description": "",
"url": "https://umbrella.crowdin.com/u/projects/173",
"cname": null,
"languageAccessPolicy": null,
"visibility": null,
"publicDownloads": null,
"logo": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJY...<truncated>...BBQmCC",
"isExternal": false,
"externalType": null,
"hasCrowdsourcing": false,
"groupId": 1
}
},
"sourceLanguage": {
"id": "en",
"name": "English",
"editorCode": "en",
"twoLettersCode": "en",
"threeLettersCode": "eng",
"locale": "en-US",
"androidCode": "en-rUS",
"osxCode": "en.lproj",
"osxLocale": "en",
"textDirection": "ltr",
"dialectOf": null
},
"affectedLanguage": {
"id": "et",
"name": "Estonian",
"editorCode": "et",
"twoLettersCode": "et",
"threeLettersCode": "est",
"locale": "et-EE",
"androidCode": "et-rEE",
"osxCode": "et.lproj",
"osxLocale": "et",
"textDirection": "ltr",
"dialectOf": null
},
"workflowStep": {
"id": 1035,
"title": "AI Review",
"type": "Application",
"languages": [],
"applicationModule": {
"applicationIdentifier": "custom-workflow-step",
"moduleKey": "review-step"
}
},
"user": {
"id": "1",
"username": "john_smith",
"fullName": "John Smith",
"avatarUrl": "https://avatar-url.com/avatar/1/small/1bc07ce78f415990547ba1b4fd5ac8a8_default.png"
}
}
}
]
}

Each string on a custom workflow step has a status per target language. The statuses you will encounter when working with the API methods:

StatusMeaning
NEED_PROCESSThe string reached the step and is waiting for the app’s decision. Counted as “to do” in the project’s progress.
TODOThe app explicitly parked the string on the step by setting an empty output ("").
DONEThe app assigned the string to one of the step’s output ports, and the string moved on in the workflow.
FAILEDWebhook delivery to the app failed. Strings in this status are shown as failed words in the project and are not resent automatically. Read more about Delivery Guarantees.
INCOMPLETEThe string was excluded from processing (e.g., hidden).
  1. Condition of Done - The app evaluates its condition of done for the received strings according to its internal logic (e.g., sending them to an AI service or performing custom validations).
  2. Updating String Status via API - After processing, the app calls the Crowdin Enterprise API to update each string’s status on the custom workflow step. This action routes the strings to the appropriate workflow step outputs.

Below are the API methods for managing string statuses on a custom workflow step. The Update String Status method is mandatory, as it finalizes string statuses and routes them to the correct workflow outputs. Another available method Get Current String Status is optional, but can help manage edge cases or advanced logic in your app.

Update String Status

Use this endpoint to update the status of strings that have reached your custom workflow step.

Crowdin Enterprise
PATCH https://{organization_domain}.api.crowdin.com/api/v2/projects/{projectId}/workflow-steps/{stepId}/languages/{languageId}/status
ParameterRequiredTypeDescription
organization_domainYesstringYour Crowdin Enterprise organization’s domain.
projectIdYesintegerNumeric identifier of your Crowdin Enterprise project.
stepIdYesintegerNumeric identifier of the custom workflow step.
languageIdYesstringTarget language code. Must be one of the step’s target languages (see the workflowStep.languages property in the webhook payload).

The request body is a JSON Patch array. Only the replace operation is supported. The path has the format /{stringId}/output, and value must be either one of the output ports declared in the module’s boundaries.outputs or an empty string:

  • A declared output port (e.g., translated) – the string is marked as Done on the step and immediately routed to the workflow step connected to that output.
  • An empty string ("") – the string is parked on the step with the To Do status. Use this to keep strings pending (e.g., visible as remaining work) until your app finishes processing them.

Request Body (example):

[
{
"op": "replace",
"path": "/1106423/output",
"value": "translated"
},
{
"op": "replace",
"path": "/1106430/output",
"value": "approved"
}
]

Response Example:

{
"data": [
{
"data": {
"stringId": 1106423,
"languageId": "uk",
"stepId": 889,
"status": "DONE",
"output": "true"
}
},
{
"data": {
"stringId": 1106430,
"languageId": "uk",
"stepId": 889,
"status": "DONE",
"output": "true"
}
}
]
}
Get Current String Status

Fetch the current statuses of strings on a custom workflow step.

Crowdin Enterprise
GET https://{organization_domain}.api.crowdin.com/api/v2/projects/{projectId}/workflow-steps/{stepId}/languages/{languageId}/status
ParameterRequiredTypeDescription
organization_domainYesstringYour Crowdin Enterprise organization’s domain.
projectIdYesintegerNumeric identifier of your Crowdin Enterprise project.
stepIdYesintegerNumeric identifier of the custom workflow step.
languageIdYesstringTarget language code.

Query parameters:

ParameterRequiredTypeDescription
stringIdsNostringFilter by string identifiers (comma-separated, up to 500 per request).
statusNostringFilter by status: TODO, DONE, INCOMPLETE, NEED_PROCESS, or FAILED.
limitNointegerMaximum number of items to retrieve.
offsetNointegerStarting offset in the collection.

Response Example:

{
"data": [
{
"data": {
"stringId": 1106423,
"languageId": "uk",
"stepId": 889,
"status": "DONE",
"output": "true"
}
},
{
"data": {
"stringId": 1106430,
"languageId": "uk",
"stepId": 889,
"status": "DONE",
"output": "true"
}
}
]
}

Treat the webhook as a notification, not a reliable queue:

  • Batching and delay – events are delivered in batches and may arrive with a short delay after strings reach the step.
  • Limited retries – if the app is unreachable or responds with an error, delivery is retried a limited number of times. After that, the affected strings are marked as Failed on the step and are not resent automatically.
  • Recovery from failures – strings in the Failed status are shown as failed words in the project. A project manager can re-trigger their processing from the workflow step in Crowdin Enterprise, which resets them to Need Process and resends the webhook event.
  • No processing deadline – strings can wait in the Need Process status indefinitely. Crowdin Enterprise does not expire or reassign them, so your app is responsible for eventually processing every string it receives.

Because delivery is not guaranteed, we recommend that your app periodically reconciles its state with Crowdin Enterprise: call the Get Current String Status endpoint with the status=NEED_PROCESS filter for each active step and language to pick up strings whose webhook events your app may have missed, and process them as usual.

Users can configure or delete a custom workflow step in the Crowdin Enterprise workflow editor. Crowdin Enterprise notifies your app about these changes via the updateSettingsUrl and deleteSettingsUrl callbacks. These notifications are your app’s source of truth about which of its steps exist and how they are configured, so we recommend persisting the received data.

  • Updating Settings (updateSettingsUrl)

    • When a user clicks Save after adding or changing the step in the workflow editor, Crowdin Enterprise sends a POST request to the updateSettingsUrl defined in the app descriptor.
    • For a step in a project workflow, the request body contains organizationId, projectId, workflowId, stepId, and settings (the step’s condition of done configuration saved by the settings UI).
    • For a step in a workflow template, the request body contains organizationId, templateId, stepId, and settings.
    • The app responds with a 2XX status to confirm successful handling of the updated configuration.
  • Deleting a Step (deleteSettingsUrl)

    • When a user deletes the step in the workflow editor, Crowdin Enterprise sends a DELETE request to the deleteSettingsUrl.
    • For a step in a project workflow, the request body contains organizationId, projectId, workflowId, and stepId. For a step in a workflow template, it contains organizationId, templateId, and stepId.
    • The app can safely remove any stored settings related to the deleted workflow step and respond with a 2XX status to confirm success.

If the workflow step provides any settings through the UI, you need to implement validation and saving of the workflow step configuration.

In the iframe UI for your custom workflow step, you need to implement a method to validate the step configuration:

window.formRef = {
validateForm: () => {
// Validate settings form
return true;
},
}

This method is called whenever Crowdin Enterprise checks if the settings are valid before saving.

To save the workflow step’s configuration, use the following method:

window.currentFormData = settings;
AP.formDataUpdated(settings);

The saved settings are delivered back to your app via the updateSettingsUrl callback when the user saves the workflow.

  1. Register an OAuth app with the scopes your app needs (at least project). Read more about Creating an OAuth application.
  2. Prepare the app descriptor: set authentication.type to crowdin_agent with your clientId, declare the agent object, one or more workflow-step-type modules, and a webhook module subscribed to the string.status_on_step.recalculation_triggered event. Declare updateSettingsUrl and deleteSettingsUrl if your step has per-step configuration, and a url settings iframe so managers can edit it.
  3. Handle the Installed event: store the received credentials, including the agentId, and obtain an API token via the crowdin_agent grant type when needed.
  4. Handle the settings callbacks: persist the data received on updateSettingsUrl – it identifies each live step (projectId/templateId, workflowId, stepId) together with its settings.
  5. Handle the webhook: acknowledge quickly with a 2xx response and queue the strings for processing. Remember that payloads arrive batched ({"events": [...]}), and verify the X-Crowdin-Signature header.
  6. Process the strings by evaluating your condition of done, and report the results with the Update String Status endpoint, assigning each string to an output port that reflects your decision, or "" to keep it parked on the step.
  7. Reconcile periodically: query the Get Current String Status endpoint with the status=NEED_PROCESS filter to pick up strings whose webhook events your app may have missed.
  8. Handle deletions: drop the stored per-step state on deleteSettingsUrl requests, and treat app uninstallation as the deletion of all steps.
  • The module is available in Crowdin Enterprise only and works in projects that use workflows.
  • The app must use the crowdin_agent authentication type and declare an agent object in the app descriptor.
  • The app must include a Webhook module subscribed to the string.status_on_step.recalculation_triggered event. Otherwise, the step cannot receive strings for processing.
  • The module is not available for serverless apps – an app backend (baseUrl) is required.
  • A step declares exactly one input group and at most two outputs. Input and output titles are 3–30 characters long. The initial port can be used only as an input.
  • The Update String Status endpoint supports only the replace operation, and the output value must be one of the step’s declared output ports or an empty string.
  • The Get Current String Status endpoint accepts up to 500 string identifiers per request.
  • Webhook delivery is best-effort: events are batched, may arrive with a delay, and are retried a limited number of times. Implement periodic reconciliation to guarantee all strings get processed.
  • The agent user must be invited as a manager to every project where the step is used. If the access is revoked, workflow validation fails and the app’s API calls are rejected.
SymptomCauseSolution
Installation fails with Only crowdin_agent authentication type is allowed for workflow-step-type module typeThe app descriptor uses crowdin_app or none authentication, or the authentication object is missingSet authentication.type to crowdin_agent, specify the clientId, and add the agent object
Installation fails with Serverless apps allow only UI module typesThe app descriptor has no baseUrlAdd a baseUrl – this module requires an app backend
Installation fails with Requested scopes exceed the access level specified in the OAuth appThe scopes in the app descriptor are broader than the scopes of the OAuth appAlign the app descriptor scopes with the OAuth app configuration
The step type doesn’t appear in the workflow editorThe app is installed in Crowdin instead of Crowdin Enterprise; the current user has no access to the module; or the app has no Webhook module subscribed to the required eventInstall the app in Crowdin Enterprise, check the module access settings, and add the Webhook module for string.status_on_step.recalculation_triggered
Workflow validation error about manager permissions for the agentThe agent user doesn’t have manager access to the projectInvite the agent user to the project as a manager
403 Forbidden on the string status endpointsThe access token was not obtained via the crowdin_agent grant type (e.g., it belongs to a regular user), or the agent is not a manager of the projectObtain the token via the crowdin_agent grant type with the agent_id parameter and verify the agent’s project role
404 Not Found on the string status endpointsThe languageId is not among the step’s target languages, or the step is not an active custom workflow stepUse the language codes from the webhook’s workflowStep.languages property and verify the step identifier
400 Bad Request when updating the string statusThe output value is not one of the step’s declared output portsSend one of the module’s boundaries.outputs[].port values or an empty string
Strings are stuck as failed words on the stepWebhook delivery to the app failedFix the app availability, then re-trigger the failed strings from the workflow step in Crowdin Enterprise
The webhook never arrivesThe webhook module is subscribed to a wrong event, or it belongs to a different app than the stepSubscribe the Webhook module of the same app to the string.status_on_step.recalculation_triggered event
The webhook arrives with a delayEvents are queued and delivered in batches by designDesign your app for asynchronous processing

Read more about App-based Workflow Steps from the organization management perspective.

Was this page helpful?