# Flows

## List flows

> Returns a list of all flows configured in the account.\
> If no flows exist in the account, a 204 response with no body will be returned.<br>

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"parameters":{"Include":{"name":"include","in":"query","required":false,"description":"Comma-separated list of fields to project into each returned record.\nTriggers **summary projection** on supported list endpoints: the server\nreturns a minimal identity set for each record (`_id`, `name`, plus a\nresource-specific always-on set like `adaptorType` on exports/imports,\nor richer defaults on `ashares`, `audit`, `httpconnectors`, `transfers`,\netc.) and adds any listed fields that exist on the record. Listed fields\nthe record doesn't carry are silently dropped.\n\nDot notation is supported for projecting nested sub-fields — e.g.\n`include=ftp.directoryPath` on `/v1/exports` returns just that nested\nfield inside `ftp` for FTP-type exports (and omits `ftp` entirely for\nnon-FTP exports).\n\nRules:\n- Value regex is `{a-z A-Z . _}` (letters, dots, underscores) plus the\n  comma separator; digits are also accepted in practice. Any other\n  character returns **400 `invalid_query_params`**.\n- Empty value (`include=`) or bare `include` is ignored — the full\n  default record is returned.\n- `include` and `exclude` are **mutually exclusive**. Passing both\n  returns **400 `invalid_query_params`**: *\"Please provide either\n  include or exclude param in the request query and not both.\"*\n- Array-bracket syntax (`include[]=...`) is not supported and can return\n  a 500.\n- Only list endpoints honor projection — on GET-by-id the parameter is\n  silently ignored.\n- A small set of list endpoints explicitly reject both `include` and\n  `exclude` with **400 `invalid_query_params`** and a message of the form\n  *\"Include or exclude query params are not applicable for `<resource>`\n  resource.\"* Known rejections: `/v1/ediprofiles`, `/v1/environments`,\n  `/v1/iClients`, `/v1/lookupcaches`, `/v1/tags`.","schema":{"type":"string"}},"Exclude":{"name":"exclude","in":"query","required":false,"description":"Comma-separated list of fields to remove from the default response on\nsupported list endpoints. Unlike `include`, `exclude` does NOT trigger\nsummary projection — callers get the standard full-record shape with the\nnamed fields stripped out.\n\nRules:\n- Value regex is `{a-z A-Z . _}` (letters, dots, underscores) plus the\n  comma separator; digits are also accepted in practice. Any other\n  character returns **400 `invalid_query_params`**.\n- Empty value (`exclude=`) is ignored.\n- Certain protected identity fields **cannot be stripped** — e.g.\n  `exclude=name` on `/v1/exports` is silently ignored and `name` remains\n  in the response. Protected sets vary per resource.\n- `include` and `exclude` are **mutually exclusive**. Passing both\n  returns **400 `invalid_query_params`**: *\"Please provide either\n  include or exclude param in the request query and not both.\"*\n- Only list endpoints honor stripping — on GET-by-id the parameter is\n  silently ignored.\n- A small set of list endpoints explicitly reject both `include` and\n  `exclude` with **400 `invalid_query_params`** and a message of the form\n  *\"Include or exclude query params are not applicable for `<resource>`\n  resource.\"* Known rejections: `/v1/ediprofiles`, `/v1/environments`,\n  `/v1/iClients`, `/v1/lookupcaches`, `/v1/tags`.","schema":{"type":"string"}}},"schemas":{"Response":{"type":"object","description":"Complete flow object as returned by the API","allOf":[{"$ref":"#/components/schemas/Request"},{"$ref":"#/components/schemas/ResourceResponse"},{"type":"object","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the flow"},"_userId":{"type":"string","format":"objectId","readOnly":true,"description":"Identifier of the user who owns the flow"},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp of the last modification to the flow"},"lastExecutedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp of the last execution of the flow"},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow was created"},"resolvedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow was resolved (errors cleared)"},"deletedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow was soft deleted"},"free":{"type":"boolean","description":"Indicates if the flow is free or requires a premium subscription"},"_templateId":{"type":"string","format":"objectId","readOnly":true,"description":"Identifier for the template used to create this flow"},"externalId":{"type":"string","description":"External identifier associated with the flow"},"_sourceId":{"type":"string","format":"objectId","readOnly":true,"description":"Identifier for the source system of the flow"},"wizardState":{"type":"string","description":"Current state of the flow setup wizard"},"setupInProgress":{"type":"boolean","description":"Flag indicating if the flow setup is currently in progress"},"__startDateHelper":{"type":"string","description":"Internal helper field for managing the start date"},"__retryAtHelper":{"type":"string","description":"Internal helper field for managing retry timestamps"},"_exportId":{"type":"string","format":"objectId","readOnly":true,"description":"Legacy field - identifier for a single export (deprecated in favor of pageGenerators)"},"_importId":{"type":"string","format":"objectId","readOnly":true,"description":"Legacy field - identifier for a single import (deprecated in favor of pageProcessors)"}}}]},"Request":{"type":"object","description":"Fields that can be sent when creating or updating a flow","properties":{"name":{"type":"string","description":"Descriptive identifier for the flow resource in human-readable format.\n\nThis string serves as the primary display name for the flow across the application UI and is used in:\n- API responses when listing flows\n- Job execution logs and monitoring dashboards\n- Flow builder UI components\n- Integration status reports\n\nWhile not required to be globally unique in the system, using descriptive, unique names is strongly recommended\nfor clarity when managing multiple integrations. The name should indicate the data flow direction and purpose.\n\nMaximum length: 255 characters\nAllowed characters: Letters, numbers, spaces, and basic punctuation\n"},"description":{"type":"string","description":"Optional free-text field that provides additional context about the flow's purpose and functionality.\n\nWhile not used for operational functionality in the API, this field serves several important purposes:\n- Helps document the business logic and data transformations applied\n- Provides context for other developers and administrators\n- Appears in the admin UI and flow listings for easier identification\n- Can be used by AI agents to better understand the flow's purpose when making recommendations\n\nBest practice is to include information about:\n- The source and destination systems\n- The type of data being synchronized\n- Any special business rules or transformations\n- Dependencies on other flows or systems\n- Run frequency and timing considerations\n\nMaximum length: 1000 characters\n"},"_integrationId":{"type":"string","format":"objectId","description":"Reference to the integration resource that this flow belongs to.\n\nThis field contains the unique identifier of an integration resource that must exist in the system.\nThe integration provides:\n- Logical grouping of related flows\n- Shared configuration and settings\n- Centralized monitoring and management\n- Common error handling patterns\n\nFormat: 24-character hexadecimal string\n"},"schedule":{"type":"string","description":"Cron expression that determines when the flow executes.\n\nThis field accepts Celigo 6-field cron expressions:\n- Format: \"second minute hour day-of-month month day-of-week\"\n- Second is always ? (no specific value)\n- Minute defaults to 5 for hourly+ schedules, or comma-separated list for sub-hourly\n- Hours use explicit comma-separated lists (NOT wildcards or step expressions)\n- Day-of-month is ? for most schedules\n- Month is * for every month\n- Day-of-week is * for every day, or specific days (0=Sun through 6=Sat)\n\nExamples:\n- \"? 0,15,30,45 * ? * *\" - Every 15 minutes\n- \"? 5 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23 ? * *\" - Every hour\n- \"? 5 0,4,8,12,16,20 ? * *\" - Every 4 hours\n- \"? 5 0 ? * *\" - Daily\n- \"? 5 9 ? * 1,2,3,4,5\" - Weekdays at 9 AM\n\nLeave empty for event-driven flows that are triggered by webhooks or other flows.\n"},"timezone":{"type":"string","description":"Timezone in which the schedule is interpreted.\n\nThis field specifies the timezone for the cron schedule:\n- Uses IANA timezone identifiers (e.g., \"America/New_York\")\n- Affects when scheduled flows execute\n- Important for daylight saving time handling\n- Defaults to UTC if not specified\n\nThe timezone ensures flows run at consistent local times regardless of:\n- Server location\n- Daylight saving time changes\n- Geographic distribution of systems\n"},"disabled":{"type":"boolean","description":"Controls whether the flow is active or disabled.\n\nWhen set to true:\n- Scheduled executions are suspended\n- The flow cannot be triggered manually or by events\n- Running jobs are allowed to complete\n- Configuration is preserved for future reactivation\n\nWhen set to false (default):\n- Flow executes according to its schedule\n- Manual and event triggers are processed\n- All configured processors and routers are active\n\nDEFAULT: true (flows are created in disabled state for safety)\n","default":true},"skipRetries":{"type":"boolean","description":"Controls whether failed executions should be retried.\n\nWhen set to true:\n- Failed jobs are not automatically retried\n- Errors are logged but no retry attempts are made\n- Useful for time-sensitive data or non-idempotent operations\n\nWhen set to false (default):\n- Failed jobs are retried according to the system retry policy\n- Exponential backoff is applied between retry attempts\n- Maximum retry attempts are determined by system configuration\n"},"pageGenerators":{"type":"array","description":"List of data sources that generate pages of records for the flow to process.\n\nPage generators are the starting points of a flow that:\n- Retrieve data from source systems via exports\n- Can run in parallel if configured\n- Generate pages of records (up to 5MB each)\n- Pass data to subsequent processors or routers\n\nEach generator can have its own schedule or inherit the flow's schedule.\n","items":{"$ref":"#/components/schemas/PageGenerator"}},"pageProcessors":{"type":"array","description":"List of processing steps that operate on data pages in sequence. Either routers or pageProcessors should be present in the flow configuration and not both.\n\nPage processors transform and route data through the flow:\n- Execute in the order defined\n- Can include exports (lookups), imports, or routers\n- Support error handling and conditional execution\n- May include response mapping for data enrichment\n","items":{"$ref":"#/components/schemas/PageProcessor"}},"routers":{"type":"array","description":"List of routing configurations that direct records to different branches. Either routers or pageProcessors should be present in the flow configuration and not both.\n\nRouters enable conditional processing by:\n- Evaluating records against defined criteria\n- Directing records to appropriate branches\n- Supporting complex business logic\n- Enabling parallel processing paths\n","items":{"$ref":"#/components/schemas/Router"}},"_runNextFlowIds":{"type":"array","description":"List of flow IDs to execute after this flow completes successfully.\n\nThis enables flow chaining where:\n- Dependent flows run automatically\n- Data pipelines can be orchestrated\n- Complex multi-step processes are coordinated\n- Success of this flow triggers the next flows\n","items":{"type":"string"}},"_runNextExportIds":{"type":"array","description":"List of export configurations to trigger after flow completion.\n\nThis field allows triggering specific exports in other flows:\n- Enables cross-flow dependencies\n- Supports selective data refreshes\n- Maintains loose coupling between flows\n","items":{"type":"object","properties":{"_flowId":{"type":"string","format":"objectId","description":"The flow containing the export to trigger"},"_exportId":{"type":"string","format":"objectId","description":"The specific export to execute"}}}},"settings":{"type":"object","description":"Custom configuration settings for the flow.\n\nThis object can contain:\n- Flow-specific parameters\n- Runtime configuration values\n- Feature flags or toggles\n- Custom business logic settings\n\nThe structure is flexible and determined by the flow's requirements.\n","additionalProperties":true},"_connectorId":{"type":"string","format":"objectId","description":"Reference to a connector template used by this flow.\n\nConnectors provide:\n- Pre-built integration templates\n- Standardized data mappings\n- Best practice configurations\n- Reusable integration patterns\n"},"runPageGeneratorsInParallel":{"type":"boolean","description":"Controls whether multiple page generators execute simultaneously.\n\nWhen set to true:\n- All page generators start at the same time\n- Improves throughput for independent data sources\n- Requires careful consideration of API rate limits\n\nWhen set to false (default):\n- Page generators execute sequentially\n- Safer for rate-limited APIs\n- Easier to debug and monitor\n"},"autoResolveMatchingTraceKeys":{"type":"boolean","description":"Enables automatic resolution of duplicate records based on trace keys.\n\nWhen set to true:\n- Records with matching trace keys are automatically resolved\n- Reduces manual intervention for known duplicates\n- Useful for idempotent operations\n\nWhen set to false (default):\n- Duplicate trace keys trigger error handling\n- Requires manual resolution\n- Provides more control over data integrity\n"},"isAbstract":{"type":"boolean","description":"Marks this flow as an abstract flow (multi-instance flow).\n\nAbstract flows define a reusable flow structure that cannot be executed directly.\nInstead, instance flows reference an abstract flow via _abstractFlowId and provide\noverrides to customize behavior per instance (different connections, schedules,\nhooks, etc.) while sharing the same flow graph.\n\nConstraints when isAbstract is true:\n- The flow cannot be triggered or run — only instance flows execute\n- Top-level pageProcessors are not allowed; all processing steps must be\n  inside routers[].branches[].pageProcessors\n- Cannot reference another abstract flow (_abstractFlowId is forbidden)\n- Cannot be set as a \"run next flow\" target\n- Cannot be unset to false while instance flows reference this flow\n- The overridesHelper field becomes available to declare which fields\n  are overridable by instances\n"},"_abstractFlowId":{"type":"string","format":"objectId","description":"Reference to an abstract flow that this instance flow inherits from.\n\nWhen specified, this flow becomes an instance flow:\n- It inherits the flow graph (pageGenerators, routers) from the abstract flow\n- The overrides object customizes connections, exports, imports, routers,\n  schedules, hooks, and other settings per instance\n- Instance flows cannot define their own pageGenerators, pageProcessors,\n  routers, or runPageGeneratorsInParallel\n- This field is immutable once set — it cannot be changed after creation\n- The referenced flow must exist and have isAbstract: true\n- Self-reference is not allowed\n\nAt runtime, the system merges the abstract flow configuration with the\ninstance flow overrides to produce the final executable flow configuration.\n"},"overrides":{"$ref":"#/components/schemas/Overrides"},"overridesHelper":{"$ref":"#/components/schemas/OverridesHelper"},"hidden":{"type":"boolean","description":"Controls visibility of the flow in user interfaces.\n\nWhen set to true:\n- Flow is hidden from standard UI views\n- Still executable and manageable via API\n- Useful for system or utility flows\n\nWhen set to false (default):\n- Flow appears in all standard UI views\n- Visible in flow lists and monitors\n"},"_flowGroupingId":{"type":"string","format":"objectId","description":"Identifier for grouping related flows together.\n\nFlow grouping enables:\n- Logical organization of related flows\n- Bulk operations on flow groups\n- Simplified monitoring and management\n- Visual grouping in UI\n"},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Reference to another flow for delta synchronization coordination.\n\nThis advanced feature:\n- Ensures this flow's delta stays behind the specified flow\n- Prevents race conditions in dependent data syncs\n- Maintains data consistency across related flows\n- Used for parent-child data relationships\n"},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Reference to a specific export for delta synchronization coordination.\n\nSimilar to _keepDeltaBehindFlowId but more granular:\n- Targets a specific export within a flow\n- Provides fine-grained control over delta timing\n- Ensures proper sequencing of dependent exports\n"},"aiDescription":{"type":"string","description":"AI-generated or user-provided description used by AI agents to understand the flow."},"aliases":{"type":"array","description":"Named aliases that map to specific resources within the flow.","items":{"type":"object","properties":{"alias":{"type":"string","description":"Alias name for the resource reference."},"_exportId":{"type":"string","format":"objectId","description":"Export referenced by this alias."},"_importId":{"type":"string","format":"objectId","description":"Import referenced by this alias."},"_flowId":{"type":"string","format":"objectId","description":"Flow referenced by this alias."},"_connectionId":{"type":"string","format":"objectId","description":"Connection referenced by this alias."}}}},"draft":{"type":"boolean","description":"Whether this flow is in draft mode and not yet published."},"draftExpiresAt":{"type":"string","format":"date-time","description":"Timestamp when the draft version of this flow expires."},"logging":{"type":"object","description":"Flow-level logging configuration.","properties":{"mode":{"type":"string","description":"Logging mode (e.g., off, on, debug)."},"debugUntil":{"type":"string","format":"date-time","description":"Timestamp until which debug-level logging is enabled."}}},"numInstances":{"type":"integer","description":"Number of instance flows derived from this abstract flow."},"preSave":{"type":"object","description":"Pre-save hook that runs a script before persisting flow changes.","properties":{"function":{"type":"string","description":"Function name to invoke in the pre-save script."},"_scriptId":{"type":"string","format":"objectId","description":"Script containing the pre-save function."}}},"settingsForm":{"type":"object","description":"Form definition used to collect flow-level settings from users.","additionalProperties":true}}},"PageGenerator":{"type":"object","description":"Configuration for a data source that generates pages of records for flow processing.\n\nPage generators are the entry points of a flow that retrieve data from source systems.\nThey can be scheduled independently or inherit the flow's schedule, and multiple generators\ncan run in parallel if configured.\n","properties":{"_exportId":{"type":"string","format":"objectId","description":"Reference to the export resource that retrieves data from the source system.\n\nThe export defines:\n- Connection to the source system\n- Query or API configuration\n- Data retrieval method (standard, delta, webhook, etc.)\n- Pagination and filtering rules\n\nFormat: 24-character hexadecimal string\n"},"schedule":{"type":"string","description":"Optional cron expression for this specific page generator.\n\nWhen specified:\n- Overrides the flow's main schedule for this generator\n- Allows different data sources to refresh at different intervals\n- Useful for sources with varying update frequencies\n\nWhen not specified:\n- Inherits the flow's schedule\n- Executes whenever the flow is triggered\n"},"skipRetries":{"type":"boolean","description":"Controls retry behavior for this specific page generator.\n\nWhen true:\n- Failed attempts are not retried\n- Errors are logged but flow may continue\n- Useful for non-critical or time-sensitive data\n\nWhen false (default):\n- Failed attempts are retried per system policy\n- Ensures data completeness\n"},"setupInProgress":{"type":"boolean","description":"Internal flag indicating if the generator configuration is being modified.\n\nThis is managed by the system and should not be set directly.\n"},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Reference to another flow for delta synchronization coordination.\n\nWhen specified:\n- This generator's delta timestamp stays behind the referenced flow\n- Prevents processing child records before parent records\n- Maintains referential integrity across flows\n"},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Reference to a specific export for delta synchronization coordination.\n\nMore granular than _keepDeltaBehindFlowId:\n- Targets a specific export's delta timestamp\n- Provides precise control over data dependencies\n- Useful for complex multi-source synchronization\n"},"__startDateHelper":{"type":"string","description":"Internal helper field for managing scheduled start dates"}},"required":["_exportId"]},"PageProcessor":{"type":"object","description":"Configuration for a processing step that operates on pages of data within a flow.\n\nPage processors can be exports (for lookups), imports (for data loading), or references\nto routers for conditional processing. They execute sequentially unless part of a router branch.\n","properties":{"type":{"type":"string","description":"Specifies the type of processor to determine which fields are relevant.\n\n- \"export\": Uses an export for data lookup/enrichment\n- \"import\": Sends data to a destination system\n","enum":["export","import"]},"_exportId":{"type":"string","format":"objectId","description":"Reference to an export resource used for data lookup or enrichment.\n\nRequired when type=\"export\". The export must be configured as a lookup\n(isLookup=true) to receive and process incoming records.\n\nCommon uses:\n- Retrieve additional details from a system\n- Validate data against a reference source\n- Enrich records with related information\n"},"_importId":{"type":"string","format":"objectId","description":"Reference to an import resource for sending data to a destination system.\n\nRequired when type=\"import\". The import defines:\n- Target system connection\n- Data mapping and transformation\n- Error handling and validation rules\n- Create/update logic\n"},"proceedOnFailure":{"type":"boolean","description":"Controls flow behavior when this processor encounters errors.\n\nWhen true:\n- Errors are logged but don't stop the flow\n- Subsequent processors continue execution\n- Failed records may be skipped\n\nWhen false (default):\n- Errors stop flow execution\n- No subsequent processors run\n- Maintains data integrity\n"},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"hooks":{"type":"object","description":"Custom code hooks for extending processor functionality","properties":{"postResponseMap":{"type":"object","description":"Hook executed after response mapping completes","properties":{"function":{"type":"string","description":"Function name to execute"},"_scriptId":{"type":"string","format":"objectId","description":"Reference to the script containing the function"}}}}},"setupInProgress":{"type":"boolean","description":"Internal flag indicating if the processor configuration is being modified.\n\nThis is managed by the system and should not be set directly.\n"}},"oneOf":[{"title":"Export processor","required":["type","_exportId"],"properties":{"_exportId":{"type":"string","format":"objectId","description":"Reference to an export resource used for data lookup or enrichment.\n\nRequired when type=\"export\". The export must be configured as a lookup\n(isLookup=true) to receive and process incoming records.\n\nCommon uses:\n- Retrieve additional details from a system\n- Validate data against a reference source\n- Enrich records with related information\n"}}},{"title":"Import processor","required":["type","_importId"],"properties":{"_importId":{"type":"string","format":"objectId","description":"Reference to an import resource for sending data to a destination system.\n\nRequired when type=\"import\". The import defines:\n- Target system connection\n- Data mapping and transformation\n- Error handling and validation rules\n- Create/update logic\n"}}}]},"ResponseMapping":{"type":"object","description":"Configuration for mapping data returned from lookups back to the original records.\n\nResponse mapping is used primarily with export processors (type=\"export\") to merge\nlookup results with the records being processed. This enables data enrichment workflows.\n","properties":{"fields":{"type":"object","description":"Field-level mapping configuration","properties":{"type":{"type":"array","description":"List of field mappings that define how to extract and map individual fields\nfrom the lookup response back to the original record.\n","items":{"type":"object","properties":{"extract":{"type":"string","description":"Path to extract data from the lookup response.\n\nUses dot notation to navigate nested objects in the response.\nCan reference arrays using index notation.\n"},"generate":{"type":"string","description":"Target field path where the extracted value will be stored.\n\nUses dot notation to specify where in the original record\nto place the extracted value.\n"},"_id":{"type":"boolean","description":"Internal identifier flag"}}}},"cLocked":{"type":"boolean","description":"Lock status preventing UI modifications.\n\nWhen true, the field mappings cannot be edited in the UI\nbut can still be modified via API.\n"}}},"lists":{"type":"object","description":"List/array mapping configuration","properties":{"type":{"type":"array","description":"List of array mappings for handling one-to-many relationships\nin lookup responses.\n","items":{"type":"object","properties":{"generate":{"type":"string","description":"Target array field where list data will be stored.\n\nThe specified field will be created as an array in the\noriginal record to hold the mapped list items.\n"},"fields":{"type":"array","description":"Field mappings within each list item.\n\nDefines how to map fields from each item in the response\narray to the corresponding item in the target array.\n","items":{"type":"object","properties":{"extract":{"type":"string","description":"Source field from each array item"},"generate":{"type":"string","description":"Target field in each array item"},"_id":{"type":"boolean","description":"Internal identifier flag"}}}},"_id":{"type":"boolean","description":"Internal identifier flag"}}}},"cLocked":{"type":"boolean","description":"Lock status preventing UI modifications.\n\nWhen true, the list mappings cannot be edited in the UI\nbut can still be modified via API.\n"}}}}},"Router":{"type":"object","description":"Configuration for conditional routing that directs records to different processing branches.\n\nRouters evaluate each record against defined criteria and route them to appropriate branches\nfor specialized processing. This enables complex business logic and conditional workflows.\n","properties":{"id":{"type":"string","description":"Unique identifier for this router within the flow.\n\nUsed to reference this router from page processors and for chaining routers.\nMust be unique within the flow's router collection.\n"},"name":{"type":"string","description":"Human-readable name for the router.\n\nDisplayed in the UI and logs to help identify the router's purpose.\n"},"routeRecordsTo":{"type":"string","description":"Strategy for routing records to branches.\n- \"first_matching_branch\": Routes to the first branch whose criteria match (most common)\n- \"all_matching_branches\": Routes to all branches whose criteria match (creates copies)\n","enum":["first_matching_branch","all_matching_branches"],"default":"first_matching_branch"},"routeRecordsUsing":{"type":"string","description":"Method used to evaluate routing criteria.\n\n- \"input_filters\": Uses declarative filter expressions\n- \"script\": Uses custom JavaScript for complex logic\n","enum":["input_filters","script"],"default":"input_filters"},"script":{"type":"object","description":"Script configuration when routeRecordsUsing=\"script\".\n\nEnables custom routing logic that can't be expressed with filters.\n","properties":{"_scriptId":{"type":"string","format":"objectId","description":"Reference to the script resource"},"function":{"type":"string","description":"Function name that returns the branch name for each record"}}},"branches":{"type":"array","description":"List of branches that define different processing paths.\n\nEach branch has its own criteria and processing steps. Records are evaluated\nagainst branch criteria in the order defined.\n","items":{"$ref":"#/components/schemas/Branch"}},"nextRouterId":{"type":"string","description":"Optional reference to another router to chain after this one.\n\nEnables sequential routing decisions where records pass through\nmultiple routers for complex branching logic.\n"}},"required":["branches"]},"Branch":{"type":"object","description":"Configuration for a single branch within a router that defines criteria and processing steps.\n\nEach branch represents a conditional path that records can take based on matching criteria.\nBranches are evaluated in order, and records are routed based on the router's strategy.\n","properties":{"name":{"type":"string","description":"Unique name for this branch within the router.\n\nUsed for:\n- Identification in logs and monitoring\n- Reference in custom routing scripts\n- Display in the UI\n\nShould be descriptive of the branch's purpose or criteria.\n"},"description":{"type":"string","description":"Optional description explaining the branch's purpose and criteria.\n\nHelps document:\n- What types of records this branch handles\n- Business logic or rules applied\n- Why this branch exists\n"},"inputFilter":{"type":"object","description":"Filter criteria that determines which records match this branch.\n\nOnly used when the router's routeRecordsUsing=\"inputFilter\".\nRecords matching these criteria will be routed to this branch.\n","properties":{"version":{"type":"string","description":"Version of the filter expression language"},"rules":{"type":"object","description":"Filter rules defining the matching criteria.\n\nThe structure depends on the version but typically includes\nlogical operators and field comparisons.\n","additionalProperties":true}}},"pageProcessors":{"type":"array","description":"List of processors that execute for records routed to this branch.\n\nThese processors:\n- Execute in sequence for records matching this branch\n- Can include exports, imports, or nested routers\n- Have the same structure as flow-level page processors\n- Continue until completion or error (unless proceedOnFailure is set)\n","items":{"$ref":"#/components/schemas/PageProcessor"}}},"required":["name"]},"Overrides":{"type":"object","description":"Configuration overrides for flows that inherit from abstract flows.\n\nWhen a flow inherits from an abstract flow template, this object allows selective\noverriding of inherited configuration while maintaining the base structure.\n","properties":{"name":{"type":"string","description":"Override for the flow's display name"},"description":{"type":"string","description":"Override for the flow's description"},"settings":{"type":"object","description":"Override for custom flow settings.\n\nAllows modifying specific settings while inheriting others from\nthe abstract flow template.\n","additionalProperties":true},"timezone":{"type":"string","description":"Override for the flow's schedule timezone"},"_runNextFlowIds":{"type":"array","description":"Override list of flows to trigger after completion","items":{"type":"string"}},"_runNextExportIds":{"type":"array","description":"Override list of exports to trigger after completion","items":{"type":"object","properties":{"_flowId":{"type":"string","description":"The flow containing the export"},"_exportId":{"type":"string","description":"The specific export to trigger"}}}},"__listenerIdsToIndex":{"type":"array","description":"Internal field for indexing listener configurations","items":{"type":"string"}},"connections":{"type":"array","description":"Override connection configurations for abstract flow connections.\n\nMaps abstract connection placeholders to concrete connection instances.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract connection being overridden"},"_id":{"type":"string","description":"Concrete connection ID to use instead"},"_borrowConcurrencyFromConnectionId":{"type":"string","description":"Optional connection to share concurrency limits with.\n\nUseful when multiple connections access the same system\nand need to share rate limiting.\n"}}}},"exports":{"type":"array","description":"Override configurations for exports in the abstract flow.\n\nAllows customizing export behavior while maintaining the flow structure.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract export being overridden"},"_id":{"type":"string","description":"Concrete export ID to use (if replacing entirely)"},"_connectionId":{"type":"string","description":"Override the connection used by this export"},"_keepDeltaBehindFlowId":{"type":"string","description":"Override delta synchronization settings"},"_keepDeltaBehindExportId":{"type":"string","description":"Override delta synchronization settings"},"schedule":{"type":"string","description":"Override the export's schedule"},"skipRetries":{"type":"boolean","description":"Override retry behavior"},"proceedOnFailure":{"type":"boolean","description":"Override error handling behavior"},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"pageSize":{"type":"integer","description":"Override page size for this export"},"dataURITemplate":{"type":"string","description":"Override URI template for error tracking"},"traceKeyTemplate":{"type":"string","description":"Override trace key generation"},"pathToMany":{"type":"string","description":"Override one-to-many path configuration"},"inputFilter":{"type":"object","description":"Override input filtering rules","properties":{"version":{"type":"string"},"rules":{"type":"object","additionalProperties":true}}},"groupByFields":{"type":"array","description":"Override grouping fields","items":{"type":"string"}},"test":{"type":"object","description":"Override test mode settings","properties":{"limit":{"type":"integer"}}},"delta":{"type":"object","description":"Override delta configuration","properties":{"dateField":{"type":"string"},"dateFormat":{"type":"string"},"startDate":{"type":"string"},"lagOffset":{"type":"integer"},"endDateField":{"type":"string"}}},"once":{"type":"object","description":"Override once export settings","properties":{"booleanField":{"type":"string"}}},"valueDelta":{"type":"object","description":"Override value delta settings","properties":{"exportedField":{"type":"string"},"pendingField":{"type":"string"}}},"webhook":{"type":"object","description":"Override webhook configuration","properties":{"token_crypt":{"type":"string"},"token_salt":{"type":"string"},"path":{"type":"string"},"key_crypt":{"type":"string"},"key_salt":{"type":"string"},"header":{"type":"string"},"username":{"type":"string"},"password_crypt":{"type":"string"},"password_salt":{"type":"string"},"successStatusCode":{"type":"integer"},"successBody":{"type":"string"},"successMediaType":{"type":"string"}}},"distributed":{"type":"object","description":"Override distributed processing settings","properties":{"bearerToken_crypt":{"type":"string"},"bearerToken_salt":{"type":"string"}}},"hooks":{"type":"object","description":"Override hook configurations"},"transform":{"type":"object","description":"Override transformation settings"},"parsers":{"type":"array","description":"Override parser configurations","items":{"type":"object"}},"filters":{"type":"object","description":"Override filter configurations"},"formSchema":{"type":"object","description":"Override form schema"},"preSaveSchema":{"type":"object","description":"Override pre-save configuration"},"settings":{"type":"object","description":"Override export-specific settings","additionalProperties":true},"idLockTemplate":{"type":"string","description":"Override ID lock template"}}}},"imports":{"type":"array","description":"Override configurations for imports in the abstract flow.\n\nSimilar structure to export overrides but for import resources.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract import being overridden"},"_connectionId":{"type":"string","description":"Override the connection used by this import"},"proceedOnFailure":{"type":"boolean","description":"Override error handling behavior"},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"idLockTemplate":{"type":"string"},"dataURITemplate":{"type":"string"},"pathToMany":{"type":"string"},"blobKeyPath":{"type":"string"},"filter":{"type":"object","additionalProperties":true},"traceKeyTemplate":{"type":"string"},"parsers":{"type":"array","items":{"type":"object"}},"hooks":{"type":"object","additionalProperties":true},"responseTransform":{"type":"object","additionalProperties":true},"mapping":{"type":"object","additionalProperties":true},"mappings":{"type":"array","items":{"type":"object"}},"lookups":{"type":"array","items":{"type":"object"}},"settingsForm":{"type":"object","additionalProperties":true},"preSave":{"type":"object","additionalProperties":true},"settings":{"type":"object","additionalProperties":true}}}},"routers":{"type":"array","description":"Override configurations for routers in the abstract flow.\n\nAllows customizing router behavior and branch configurations.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract router being overridden"},"name":{"type":"string","description":"Override router name"},"script":{"type":"object","description":"Override routing script","properties":{"_scriptId":{"type":"string"},"function":{"type":"string"}}},"branches":{"type":"array","description":"Override branch configurations","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract branch being overridden"},"name":{"type":"string"},"description":{"type":"string"},"inputFilter":{"type":"object","properties":{"version":{"type":"string"},"rules":{"type":"object","additionalProperties":true}}}}}}}}}}},"OverridesHelper":{"type":"object","description":"Metadata for abstract flows that declares which fields in the flow's connections,\nexports, imports, and routers are overridable by instance flows.\n\nOnly valid on abstract flows (isAbstract: true). The backend rejects this field\non non-abstract flows. Each entry references a component of the abstract flow by\nits ID and lists the field names that instance flows are allowed to override.\n","properties":{"fields":{"type":"array","description":"Flow-level field names that instance flows may override (e.g., \"schedule\", \"timezone\")","items":{"type":"string"}},"connections":{"type":"array","description":"Declares which connection-level fields are overridable per abstract flow connection.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the connection in the abstract flow"},"fields":{"type":"array","description":"Field names on this connection that instance flows may override","items":{"type":"string"}}}}},"exports":{"type":"array","description":"Declares which export-level fields are overridable per abstract flow export.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the export in the abstract flow"},"fields":{"type":"array","description":"Field names on this export that instance flows may override","items":{"type":"string"}}}}},"imports":{"type":"array","description":"Declares which import-level fields are overridable per abstract flow import.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the import in the abstract flow"},"fields":{"type":"array","description":"Field names on this import that instance flows may override","items":{"type":"string"}}}}},"routers":{"type":"array","description":"Declares which router-level and branch-level fields are overridable per abstract flow router.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the router in the abstract flow"},"fields":{"type":"array","description":"Field names on this router that instance flows may override","items":{"type":"string"}},"branches":{"type":"array","description":"Per-branch override declarations","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"Index or ID of the branch in the abstract flow router"},"fields":{"type":"array","description":"Field names on this branch that instance flows may override","items":{"type":"string"}}}}}}}}}},"ResourceResponse":{"type":"object","description":"Core response fields shared by all Celigo resources","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the resource.\n\nThe _id is used in:\n- API endpoints that operate on a specific resource (e.g., GET, PUT, DELETE)\n- References from other resources (e.g., flows that use this resource)\n- Job history and error tracking\n\nFormat: 24-character hexadecimal string\n"},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp indicating when the resource was initially created.\n\nThis read-only field is automatically set during resource creation and cannot\nbe modified. It provides an audit trail for when the resource was first added\nto the system, which can be useful for:\n\n- Resource lifecycle management\n- Audit and compliance reporting\n- Troubleshooting integration timelines\n- Identifying older resources that may need review\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix).\n"},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp indicating when the resource was most recently updated.\n\nThis read-only field is automatically updated whenever any property of the\nresource is modified. It provides an audit trail that can be used for:\n\n- Determining if a resource has changed since it was last reviewed\n- Monitoring configuration changes during troubleshooting\n- Implementing cache invalidation strategies\n- Synchronizing related resources based on modification time\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix)\nand will always be equal to or later than the createdAt timestamp.\n"},"deletedAt":{"type":["string","null"],"format":"date-time","readOnly":true,"description":"Timestamp indicating when the resource was marked for deletion.\n\nWhen this field is present and contains a valid timestamp, it indicates\nthat the resource has been soft-deleted (moved to the recycle bin) but not\nyet permanently removed from the system. This allows for recovery of\naccidentally deleted resources within a specified retention period.\n\nThe deletedAt timestamp enables:\n- Filtering deleted resources from active resource listings\n- Implementing time-based retention policies for permanent deletion\n- Tracking deletion events for audit and compliance purposes\n- Resource recovery workflows with clear timeframes\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix).\nWhen null or absent, the resource is considered active.\n"}},"required":["_id"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}}},"paths":{"/v1/flows":{"get":{"summary":"List flows","description":"Returns a list of all flows configured in the account.\nIf no flows exist in the account, a 204 response with no body will be returned.\n","operationId":"listFlows","tags":["Flows"],"parameters":[{"$ref":"#/components/parameters/Include"},{"$ref":"#/components/parameters/Exclude"}],"responses":{"200":{"description":"Successfully retrieved list of flows","headers":{"Link":{"description":"RFC-5988 pagination links. When more pages remain, includes a `<...>; rel=\"next\"` entry;\nabsent on the final page.\n","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Response"}}}}},"204":{"description":"No flows exist in the account"},"401":{"$ref":"#/components/responses/401-unauthorized"}}}}}}
```

## Create a flow

> Creates a new flow configuration that orchestrates data movement between systems.<br>

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"Request":{"type":"object","description":"Fields that can be sent when creating or updating a flow","properties":{"name":{"type":"string","description":"Descriptive identifier for the flow resource in human-readable format.\n\nThis string serves as the primary display name for the flow across the application UI and is used in:\n- API responses when listing flows\n- Job execution logs and monitoring dashboards\n- Flow builder UI components\n- Integration status reports\n\nWhile not required to be globally unique in the system, using descriptive, unique names is strongly recommended\nfor clarity when managing multiple integrations. The name should indicate the data flow direction and purpose.\n\nMaximum length: 255 characters\nAllowed characters: Letters, numbers, spaces, and basic punctuation\n"},"description":{"type":"string","description":"Optional free-text field that provides additional context about the flow's purpose and functionality.\n\nWhile not used for operational functionality in the API, this field serves several important purposes:\n- Helps document the business logic and data transformations applied\n- Provides context for other developers and administrators\n- Appears in the admin UI and flow listings for easier identification\n- Can be used by AI agents to better understand the flow's purpose when making recommendations\n\nBest practice is to include information about:\n- The source and destination systems\n- The type of data being synchronized\n- Any special business rules or transformations\n- Dependencies on other flows or systems\n- Run frequency and timing considerations\n\nMaximum length: 1000 characters\n"},"_integrationId":{"type":"string","format":"objectId","description":"Reference to the integration resource that this flow belongs to.\n\nThis field contains the unique identifier of an integration resource that must exist in the system.\nThe integration provides:\n- Logical grouping of related flows\n- Shared configuration and settings\n- Centralized monitoring and management\n- Common error handling patterns\n\nFormat: 24-character hexadecimal string\n"},"schedule":{"type":"string","description":"Cron expression that determines when the flow executes.\n\nThis field accepts Celigo 6-field cron expressions:\n- Format: \"second minute hour day-of-month month day-of-week\"\n- Second is always ? (no specific value)\n- Minute defaults to 5 for hourly+ schedules, or comma-separated list for sub-hourly\n- Hours use explicit comma-separated lists (NOT wildcards or step expressions)\n- Day-of-month is ? for most schedules\n- Month is * for every month\n- Day-of-week is * for every day, or specific days (0=Sun through 6=Sat)\n\nExamples:\n- \"? 0,15,30,45 * ? * *\" - Every 15 minutes\n- \"? 5 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23 ? * *\" - Every hour\n- \"? 5 0,4,8,12,16,20 ? * *\" - Every 4 hours\n- \"? 5 0 ? * *\" - Daily\n- \"? 5 9 ? * 1,2,3,4,5\" - Weekdays at 9 AM\n\nLeave empty for event-driven flows that are triggered by webhooks or other flows.\n"},"timezone":{"type":"string","description":"Timezone in which the schedule is interpreted.\n\nThis field specifies the timezone for the cron schedule:\n- Uses IANA timezone identifiers (e.g., \"America/New_York\")\n- Affects when scheduled flows execute\n- Important for daylight saving time handling\n- Defaults to UTC if not specified\n\nThe timezone ensures flows run at consistent local times regardless of:\n- Server location\n- Daylight saving time changes\n- Geographic distribution of systems\n"},"disabled":{"type":"boolean","description":"Controls whether the flow is active or disabled.\n\nWhen set to true:\n- Scheduled executions are suspended\n- The flow cannot be triggered manually or by events\n- Running jobs are allowed to complete\n- Configuration is preserved for future reactivation\n\nWhen set to false (default):\n- Flow executes according to its schedule\n- Manual and event triggers are processed\n- All configured processors and routers are active\n\nDEFAULT: true (flows are created in disabled state for safety)\n","default":true},"skipRetries":{"type":"boolean","description":"Controls whether failed executions should be retried.\n\nWhen set to true:\n- Failed jobs are not automatically retried\n- Errors are logged but no retry attempts are made\n- Useful for time-sensitive data or non-idempotent operations\n\nWhen set to false (default):\n- Failed jobs are retried according to the system retry policy\n- Exponential backoff is applied between retry attempts\n- Maximum retry attempts are determined by system configuration\n"},"pageGenerators":{"type":"array","description":"List of data sources that generate pages of records for the flow to process.\n\nPage generators are the starting points of a flow that:\n- Retrieve data from source systems via exports\n- Can run in parallel if configured\n- Generate pages of records (up to 5MB each)\n- Pass data to subsequent processors or routers\n\nEach generator can have its own schedule or inherit the flow's schedule.\n","items":{"$ref":"#/components/schemas/PageGenerator"}},"pageProcessors":{"type":"array","description":"List of processing steps that operate on data pages in sequence. Either routers or pageProcessors should be present in the flow configuration and not both.\n\nPage processors transform and route data through the flow:\n- Execute in the order defined\n- Can include exports (lookups), imports, or routers\n- Support error handling and conditional execution\n- May include response mapping for data enrichment\n","items":{"$ref":"#/components/schemas/PageProcessor"}},"routers":{"type":"array","description":"List of routing configurations that direct records to different branches. Either routers or pageProcessors should be present in the flow configuration and not both.\n\nRouters enable conditional processing by:\n- Evaluating records against defined criteria\n- Directing records to appropriate branches\n- Supporting complex business logic\n- Enabling parallel processing paths\n","items":{"$ref":"#/components/schemas/Router"}},"_runNextFlowIds":{"type":"array","description":"List of flow IDs to execute after this flow completes successfully.\n\nThis enables flow chaining where:\n- Dependent flows run automatically\n- Data pipelines can be orchestrated\n- Complex multi-step processes are coordinated\n- Success of this flow triggers the next flows\n","items":{"type":"string"}},"_runNextExportIds":{"type":"array","description":"List of export configurations to trigger after flow completion.\n\nThis field allows triggering specific exports in other flows:\n- Enables cross-flow dependencies\n- Supports selective data refreshes\n- Maintains loose coupling between flows\n","items":{"type":"object","properties":{"_flowId":{"type":"string","format":"objectId","description":"The flow containing the export to trigger"},"_exportId":{"type":"string","format":"objectId","description":"The specific export to execute"}}}},"settings":{"type":"object","description":"Custom configuration settings for the flow.\n\nThis object can contain:\n- Flow-specific parameters\n- Runtime configuration values\n- Feature flags or toggles\n- Custom business logic settings\n\nThe structure is flexible and determined by the flow's requirements.\n","additionalProperties":true},"_connectorId":{"type":"string","format":"objectId","description":"Reference to a connector template used by this flow.\n\nConnectors provide:\n- Pre-built integration templates\n- Standardized data mappings\n- Best practice configurations\n- Reusable integration patterns\n"},"runPageGeneratorsInParallel":{"type":"boolean","description":"Controls whether multiple page generators execute simultaneously.\n\nWhen set to true:\n- All page generators start at the same time\n- Improves throughput for independent data sources\n- Requires careful consideration of API rate limits\n\nWhen set to false (default):\n- Page generators execute sequentially\n- Safer for rate-limited APIs\n- Easier to debug and monitor\n"},"autoResolveMatchingTraceKeys":{"type":"boolean","description":"Enables automatic resolution of duplicate records based on trace keys.\n\nWhen set to true:\n- Records with matching trace keys are automatically resolved\n- Reduces manual intervention for known duplicates\n- Useful for idempotent operations\n\nWhen set to false (default):\n- Duplicate trace keys trigger error handling\n- Requires manual resolution\n- Provides more control over data integrity\n"},"isAbstract":{"type":"boolean","description":"Marks this flow as an abstract flow (multi-instance flow).\n\nAbstract flows define a reusable flow structure that cannot be executed directly.\nInstead, instance flows reference an abstract flow via _abstractFlowId and provide\noverrides to customize behavior per instance (different connections, schedules,\nhooks, etc.) while sharing the same flow graph.\n\nConstraints when isAbstract is true:\n- The flow cannot be triggered or run — only instance flows execute\n- Top-level pageProcessors are not allowed; all processing steps must be\n  inside routers[].branches[].pageProcessors\n- Cannot reference another abstract flow (_abstractFlowId is forbidden)\n- Cannot be set as a \"run next flow\" target\n- Cannot be unset to false while instance flows reference this flow\n- The overridesHelper field becomes available to declare which fields\n  are overridable by instances\n"},"_abstractFlowId":{"type":"string","format":"objectId","description":"Reference to an abstract flow that this instance flow inherits from.\n\nWhen specified, this flow becomes an instance flow:\n- It inherits the flow graph (pageGenerators, routers) from the abstract flow\n- The overrides object customizes connections, exports, imports, routers,\n  schedules, hooks, and other settings per instance\n- Instance flows cannot define their own pageGenerators, pageProcessors,\n  routers, or runPageGeneratorsInParallel\n- This field is immutable once set — it cannot be changed after creation\n- The referenced flow must exist and have isAbstract: true\n- Self-reference is not allowed\n\nAt runtime, the system merges the abstract flow configuration with the\ninstance flow overrides to produce the final executable flow configuration.\n"},"overrides":{"$ref":"#/components/schemas/Overrides"},"overridesHelper":{"$ref":"#/components/schemas/OverridesHelper"},"hidden":{"type":"boolean","description":"Controls visibility of the flow in user interfaces.\n\nWhen set to true:\n- Flow is hidden from standard UI views\n- Still executable and manageable via API\n- Useful for system or utility flows\n\nWhen set to false (default):\n- Flow appears in all standard UI views\n- Visible in flow lists and monitors\n"},"_flowGroupingId":{"type":"string","format":"objectId","description":"Identifier for grouping related flows together.\n\nFlow grouping enables:\n- Logical organization of related flows\n- Bulk operations on flow groups\n- Simplified monitoring and management\n- Visual grouping in UI\n"},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Reference to another flow for delta synchronization coordination.\n\nThis advanced feature:\n- Ensures this flow's delta stays behind the specified flow\n- Prevents race conditions in dependent data syncs\n- Maintains data consistency across related flows\n- Used for parent-child data relationships\n"},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Reference to a specific export for delta synchronization coordination.\n\nSimilar to _keepDeltaBehindFlowId but more granular:\n- Targets a specific export within a flow\n- Provides fine-grained control over delta timing\n- Ensures proper sequencing of dependent exports\n"},"aiDescription":{"type":"string","description":"AI-generated or user-provided description used by AI agents to understand the flow."},"aliases":{"type":"array","description":"Named aliases that map to specific resources within the flow.","items":{"type":"object","properties":{"alias":{"type":"string","description":"Alias name for the resource reference."},"_exportId":{"type":"string","format":"objectId","description":"Export referenced by this alias."},"_importId":{"type":"string","format":"objectId","description":"Import referenced by this alias."},"_flowId":{"type":"string","format":"objectId","description":"Flow referenced by this alias."},"_connectionId":{"type":"string","format":"objectId","description":"Connection referenced by this alias."}}}},"draft":{"type":"boolean","description":"Whether this flow is in draft mode and not yet published."},"draftExpiresAt":{"type":"string","format":"date-time","description":"Timestamp when the draft version of this flow expires."},"logging":{"type":"object","description":"Flow-level logging configuration.","properties":{"mode":{"type":"string","description":"Logging mode (e.g., off, on, debug)."},"debugUntil":{"type":"string","format":"date-time","description":"Timestamp until which debug-level logging is enabled."}}},"numInstances":{"type":"integer","description":"Number of instance flows derived from this abstract flow."},"preSave":{"type":"object","description":"Pre-save hook that runs a script before persisting flow changes.","properties":{"function":{"type":"string","description":"Function name to invoke in the pre-save script."},"_scriptId":{"type":"string","format":"objectId","description":"Script containing the pre-save function."}}},"settingsForm":{"type":"object","description":"Form definition used to collect flow-level settings from users.","additionalProperties":true}}},"PageGenerator":{"type":"object","description":"Configuration for a data source that generates pages of records for flow processing.\n\nPage generators are the entry points of a flow that retrieve data from source systems.\nThey can be scheduled independently or inherit the flow's schedule, and multiple generators\ncan run in parallel if configured.\n","properties":{"_exportId":{"type":"string","format":"objectId","description":"Reference to the export resource that retrieves data from the source system.\n\nThe export defines:\n- Connection to the source system\n- Query or API configuration\n- Data retrieval method (standard, delta, webhook, etc.)\n- Pagination and filtering rules\n\nFormat: 24-character hexadecimal string\n"},"schedule":{"type":"string","description":"Optional cron expression for this specific page generator.\n\nWhen specified:\n- Overrides the flow's main schedule for this generator\n- Allows different data sources to refresh at different intervals\n- Useful for sources with varying update frequencies\n\nWhen not specified:\n- Inherits the flow's schedule\n- Executes whenever the flow is triggered\n"},"skipRetries":{"type":"boolean","description":"Controls retry behavior for this specific page generator.\n\nWhen true:\n- Failed attempts are not retried\n- Errors are logged but flow may continue\n- Useful for non-critical or time-sensitive data\n\nWhen false (default):\n- Failed attempts are retried per system policy\n- Ensures data completeness\n"},"setupInProgress":{"type":"boolean","description":"Internal flag indicating if the generator configuration is being modified.\n\nThis is managed by the system and should not be set directly.\n"},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Reference to another flow for delta synchronization coordination.\n\nWhen specified:\n- This generator's delta timestamp stays behind the referenced flow\n- Prevents processing child records before parent records\n- Maintains referential integrity across flows\n"},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Reference to a specific export for delta synchronization coordination.\n\nMore granular than _keepDeltaBehindFlowId:\n- Targets a specific export's delta timestamp\n- Provides precise control over data dependencies\n- Useful for complex multi-source synchronization\n"},"__startDateHelper":{"type":"string","description":"Internal helper field for managing scheduled start dates"}},"required":["_exportId"]},"PageProcessor":{"type":"object","description":"Configuration for a processing step that operates on pages of data within a flow.\n\nPage processors can be exports (for lookups), imports (for data loading), or references\nto routers for conditional processing. They execute sequentially unless part of a router branch.\n","properties":{"type":{"type":"string","description":"Specifies the type of processor to determine which fields are relevant.\n\n- \"export\": Uses an export for data lookup/enrichment\n- \"import\": Sends data to a destination system\n","enum":["export","import"]},"_exportId":{"type":"string","format":"objectId","description":"Reference to an export resource used for data lookup or enrichment.\n\nRequired when type=\"export\". The export must be configured as a lookup\n(isLookup=true) to receive and process incoming records.\n\nCommon uses:\n- Retrieve additional details from a system\n- Validate data against a reference source\n- Enrich records with related information\n"},"_importId":{"type":"string","format":"objectId","description":"Reference to an import resource for sending data to a destination system.\n\nRequired when type=\"import\". The import defines:\n- Target system connection\n- Data mapping and transformation\n- Error handling and validation rules\n- Create/update logic\n"},"proceedOnFailure":{"type":"boolean","description":"Controls flow behavior when this processor encounters errors.\n\nWhen true:\n- Errors are logged but don't stop the flow\n- Subsequent processors continue execution\n- Failed records may be skipped\n\nWhen false (default):\n- Errors stop flow execution\n- No subsequent processors run\n- Maintains data integrity\n"},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"hooks":{"type":"object","description":"Custom code hooks for extending processor functionality","properties":{"postResponseMap":{"type":"object","description":"Hook executed after response mapping completes","properties":{"function":{"type":"string","description":"Function name to execute"},"_scriptId":{"type":"string","format":"objectId","description":"Reference to the script containing the function"}}}}},"setupInProgress":{"type":"boolean","description":"Internal flag indicating if the processor configuration is being modified.\n\nThis is managed by the system and should not be set directly.\n"}},"oneOf":[{"title":"Export processor","required":["type","_exportId"],"properties":{"_exportId":{"type":"string","format":"objectId","description":"Reference to an export resource used for data lookup or enrichment.\n\nRequired when type=\"export\". The export must be configured as a lookup\n(isLookup=true) to receive and process incoming records.\n\nCommon uses:\n- Retrieve additional details from a system\n- Validate data against a reference source\n- Enrich records with related information\n"}}},{"title":"Import processor","required":["type","_importId"],"properties":{"_importId":{"type":"string","format":"objectId","description":"Reference to an import resource for sending data to a destination system.\n\nRequired when type=\"import\". The import defines:\n- Target system connection\n- Data mapping and transformation\n- Error handling and validation rules\n- Create/update logic\n"}}}]},"ResponseMapping":{"type":"object","description":"Configuration for mapping data returned from lookups back to the original records.\n\nResponse mapping is used primarily with export processors (type=\"export\") to merge\nlookup results with the records being processed. This enables data enrichment workflows.\n","properties":{"fields":{"type":"object","description":"Field-level mapping configuration","properties":{"type":{"type":"array","description":"List of field mappings that define how to extract and map individual fields\nfrom the lookup response back to the original record.\n","items":{"type":"object","properties":{"extract":{"type":"string","description":"Path to extract data from the lookup response.\n\nUses dot notation to navigate nested objects in the response.\nCan reference arrays using index notation.\n"},"generate":{"type":"string","description":"Target field path where the extracted value will be stored.\n\nUses dot notation to specify where in the original record\nto place the extracted value.\n"},"_id":{"type":"boolean","description":"Internal identifier flag"}}}},"cLocked":{"type":"boolean","description":"Lock status preventing UI modifications.\n\nWhen true, the field mappings cannot be edited in the UI\nbut can still be modified via API.\n"}}},"lists":{"type":"object","description":"List/array mapping configuration","properties":{"type":{"type":"array","description":"List of array mappings for handling one-to-many relationships\nin lookup responses.\n","items":{"type":"object","properties":{"generate":{"type":"string","description":"Target array field where list data will be stored.\n\nThe specified field will be created as an array in the\noriginal record to hold the mapped list items.\n"},"fields":{"type":"array","description":"Field mappings within each list item.\n\nDefines how to map fields from each item in the response\narray to the corresponding item in the target array.\n","items":{"type":"object","properties":{"extract":{"type":"string","description":"Source field from each array item"},"generate":{"type":"string","description":"Target field in each array item"},"_id":{"type":"boolean","description":"Internal identifier flag"}}}},"_id":{"type":"boolean","description":"Internal identifier flag"}}}},"cLocked":{"type":"boolean","description":"Lock status preventing UI modifications.\n\nWhen true, the list mappings cannot be edited in the UI\nbut can still be modified via API.\n"}}}}},"Router":{"type":"object","description":"Configuration for conditional routing that directs records to different processing branches.\n\nRouters evaluate each record against defined criteria and route them to appropriate branches\nfor specialized processing. This enables complex business logic and conditional workflows.\n","properties":{"id":{"type":"string","description":"Unique identifier for this router within the flow.\n\nUsed to reference this router from page processors and for chaining routers.\nMust be unique within the flow's router collection.\n"},"name":{"type":"string","description":"Human-readable name for the router.\n\nDisplayed in the UI and logs to help identify the router's purpose.\n"},"routeRecordsTo":{"type":"string","description":"Strategy for routing records to branches.\n- \"first_matching_branch\": Routes to the first branch whose criteria match (most common)\n- \"all_matching_branches\": Routes to all branches whose criteria match (creates copies)\n","enum":["first_matching_branch","all_matching_branches"],"default":"first_matching_branch"},"routeRecordsUsing":{"type":"string","description":"Method used to evaluate routing criteria.\n\n- \"input_filters\": Uses declarative filter expressions\n- \"script\": Uses custom JavaScript for complex logic\n","enum":["input_filters","script"],"default":"input_filters"},"script":{"type":"object","description":"Script configuration when routeRecordsUsing=\"script\".\n\nEnables custom routing logic that can't be expressed with filters.\n","properties":{"_scriptId":{"type":"string","format":"objectId","description":"Reference to the script resource"},"function":{"type":"string","description":"Function name that returns the branch name for each record"}}},"branches":{"type":"array","description":"List of branches that define different processing paths.\n\nEach branch has its own criteria and processing steps. Records are evaluated\nagainst branch criteria in the order defined.\n","items":{"$ref":"#/components/schemas/Branch"}},"nextRouterId":{"type":"string","description":"Optional reference to another router to chain after this one.\n\nEnables sequential routing decisions where records pass through\nmultiple routers for complex branching logic.\n"}},"required":["branches"]},"Branch":{"type":"object","description":"Configuration for a single branch within a router that defines criteria and processing steps.\n\nEach branch represents a conditional path that records can take based on matching criteria.\nBranches are evaluated in order, and records are routed based on the router's strategy.\n","properties":{"name":{"type":"string","description":"Unique name for this branch within the router.\n\nUsed for:\n- Identification in logs and monitoring\n- Reference in custom routing scripts\n- Display in the UI\n\nShould be descriptive of the branch's purpose or criteria.\n"},"description":{"type":"string","description":"Optional description explaining the branch's purpose and criteria.\n\nHelps document:\n- What types of records this branch handles\n- Business logic or rules applied\n- Why this branch exists\n"},"inputFilter":{"type":"object","description":"Filter criteria that determines which records match this branch.\n\nOnly used when the router's routeRecordsUsing=\"inputFilter\".\nRecords matching these criteria will be routed to this branch.\n","properties":{"version":{"type":"string","description":"Version of the filter expression language"},"rules":{"type":"object","description":"Filter rules defining the matching criteria.\n\nThe structure depends on the version but typically includes\nlogical operators and field comparisons.\n","additionalProperties":true}}},"pageProcessors":{"type":"array","description":"List of processors that execute for records routed to this branch.\n\nThese processors:\n- Execute in sequence for records matching this branch\n- Can include exports, imports, or nested routers\n- Have the same structure as flow-level page processors\n- Continue until completion or error (unless proceedOnFailure is set)\n","items":{"$ref":"#/components/schemas/PageProcessor"}}},"required":["name"]},"Overrides":{"type":"object","description":"Configuration overrides for flows that inherit from abstract flows.\n\nWhen a flow inherits from an abstract flow template, this object allows selective\noverriding of inherited configuration while maintaining the base structure.\n","properties":{"name":{"type":"string","description":"Override for the flow's display name"},"description":{"type":"string","description":"Override for the flow's description"},"settings":{"type":"object","description":"Override for custom flow settings.\n\nAllows modifying specific settings while inheriting others from\nthe abstract flow template.\n","additionalProperties":true},"timezone":{"type":"string","description":"Override for the flow's schedule timezone"},"_runNextFlowIds":{"type":"array","description":"Override list of flows to trigger after completion","items":{"type":"string"}},"_runNextExportIds":{"type":"array","description":"Override list of exports to trigger after completion","items":{"type":"object","properties":{"_flowId":{"type":"string","description":"The flow containing the export"},"_exportId":{"type":"string","description":"The specific export to trigger"}}}},"__listenerIdsToIndex":{"type":"array","description":"Internal field for indexing listener configurations","items":{"type":"string"}},"connections":{"type":"array","description":"Override connection configurations for abstract flow connections.\n\nMaps abstract connection placeholders to concrete connection instances.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract connection being overridden"},"_id":{"type":"string","description":"Concrete connection ID to use instead"},"_borrowConcurrencyFromConnectionId":{"type":"string","description":"Optional connection to share concurrency limits with.\n\nUseful when multiple connections access the same system\nand need to share rate limiting.\n"}}}},"exports":{"type":"array","description":"Override configurations for exports in the abstract flow.\n\nAllows customizing export behavior while maintaining the flow structure.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract export being overridden"},"_id":{"type":"string","description":"Concrete export ID to use (if replacing entirely)"},"_connectionId":{"type":"string","description":"Override the connection used by this export"},"_keepDeltaBehindFlowId":{"type":"string","description":"Override delta synchronization settings"},"_keepDeltaBehindExportId":{"type":"string","description":"Override delta synchronization settings"},"schedule":{"type":"string","description":"Override the export's schedule"},"skipRetries":{"type":"boolean","description":"Override retry behavior"},"proceedOnFailure":{"type":"boolean","description":"Override error handling behavior"},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"pageSize":{"type":"integer","description":"Override page size for this export"},"dataURITemplate":{"type":"string","description":"Override URI template for error tracking"},"traceKeyTemplate":{"type":"string","description":"Override trace key generation"},"pathToMany":{"type":"string","description":"Override one-to-many path configuration"},"inputFilter":{"type":"object","description":"Override input filtering rules","properties":{"version":{"type":"string"},"rules":{"type":"object","additionalProperties":true}}},"groupByFields":{"type":"array","description":"Override grouping fields","items":{"type":"string"}},"test":{"type":"object","description":"Override test mode settings","properties":{"limit":{"type":"integer"}}},"delta":{"type":"object","description":"Override delta configuration","properties":{"dateField":{"type":"string"},"dateFormat":{"type":"string"},"startDate":{"type":"string"},"lagOffset":{"type":"integer"},"endDateField":{"type":"string"}}},"once":{"type":"object","description":"Override once export settings","properties":{"booleanField":{"type":"string"}}},"valueDelta":{"type":"object","description":"Override value delta settings","properties":{"exportedField":{"type":"string"},"pendingField":{"type":"string"}}},"webhook":{"type":"object","description":"Override webhook configuration","properties":{"token_crypt":{"type":"string"},"token_salt":{"type":"string"},"path":{"type":"string"},"key_crypt":{"type":"string"},"key_salt":{"type":"string"},"header":{"type":"string"},"username":{"type":"string"},"password_crypt":{"type":"string"},"password_salt":{"type":"string"},"successStatusCode":{"type":"integer"},"successBody":{"type":"string"},"successMediaType":{"type":"string"}}},"distributed":{"type":"object","description":"Override distributed processing settings","properties":{"bearerToken_crypt":{"type":"string"},"bearerToken_salt":{"type":"string"}}},"hooks":{"type":"object","description":"Override hook configurations"},"transform":{"type":"object","description":"Override transformation settings"},"parsers":{"type":"array","description":"Override parser configurations","items":{"type":"object"}},"filters":{"type":"object","description":"Override filter configurations"},"formSchema":{"type":"object","description":"Override form schema"},"preSaveSchema":{"type":"object","description":"Override pre-save configuration"},"settings":{"type":"object","description":"Override export-specific settings","additionalProperties":true},"idLockTemplate":{"type":"string","description":"Override ID lock template"}}}},"imports":{"type":"array","description":"Override configurations for imports in the abstract flow.\n\nSimilar structure to export overrides but for import resources.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract import being overridden"},"_connectionId":{"type":"string","description":"Override the connection used by this import"},"proceedOnFailure":{"type":"boolean","description":"Override error handling behavior"},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"idLockTemplate":{"type":"string"},"dataURITemplate":{"type":"string"},"pathToMany":{"type":"string"},"blobKeyPath":{"type":"string"},"filter":{"type":"object","additionalProperties":true},"traceKeyTemplate":{"type":"string"},"parsers":{"type":"array","items":{"type":"object"}},"hooks":{"type":"object","additionalProperties":true},"responseTransform":{"type":"object","additionalProperties":true},"mapping":{"type":"object","additionalProperties":true},"mappings":{"type":"array","items":{"type":"object"}},"lookups":{"type":"array","items":{"type":"object"}},"settingsForm":{"type":"object","additionalProperties":true},"preSave":{"type":"object","additionalProperties":true},"settings":{"type":"object","additionalProperties":true}}}},"routers":{"type":"array","description":"Override configurations for routers in the abstract flow.\n\nAllows customizing router behavior and branch configurations.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract router being overridden"},"name":{"type":"string","description":"Override router name"},"script":{"type":"object","description":"Override routing script","properties":{"_scriptId":{"type":"string"},"function":{"type":"string"}}},"branches":{"type":"array","description":"Override branch configurations","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract branch being overridden"},"name":{"type":"string"},"description":{"type":"string"},"inputFilter":{"type":"object","properties":{"version":{"type":"string"},"rules":{"type":"object","additionalProperties":true}}}}}}}}}}},"OverridesHelper":{"type":"object","description":"Metadata for abstract flows that declares which fields in the flow's connections,\nexports, imports, and routers are overridable by instance flows.\n\nOnly valid on abstract flows (isAbstract: true). The backend rejects this field\non non-abstract flows. Each entry references a component of the abstract flow by\nits ID and lists the field names that instance flows are allowed to override.\n","properties":{"fields":{"type":"array","description":"Flow-level field names that instance flows may override (e.g., \"schedule\", \"timezone\")","items":{"type":"string"}},"connections":{"type":"array","description":"Declares which connection-level fields are overridable per abstract flow connection.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the connection in the abstract flow"},"fields":{"type":"array","description":"Field names on this connection that instance flows may override","items":{"type":"string"}}}}},"exports":{"type":"array","description":"Declares which export-level fields are overridable per abstract flow export.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the export in the abstract flow"},"fields":{"type":"array","description":"Field names on this export that instance flows may override","items":{"type":"string"}}}}},"imports":{"type":"array","description":"Declares which import-level fields are overridable per abstract flow import.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the import in the abstract flow"},"fields":{"type":"array","description":"Field names on this import that instance flows may override","items":{"type":"string"}}}}},"routers":{"type":"array","description":"Declares which router-level and branch-level fields are overridable per abstract flow router.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the router in the abstract flow"},"fields":{"type":"array","description":"Field names on this router that instance flows may override","items":{"type":"string"}},"branches":{"type":"array","description":"Per-branch override declarations","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"Index or ID of the branch in the abstract flow router"},"fields":{"type":"array","description":"Field names on this branch that instance flows may override","items":{"type":"string"}}}}}}}}}},"Response":{"type":"object","description":"Complete flow object as returned by the API","allOf":[{"$ref":"#/components/schemas/Request"},{"$ref":"#/components/schemas/ResourceResponse"},{"type":"object","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the flow"},"_userId":{"type":"string","format":"objectId","readOnly":true,"description":"Identifier of the user who owns the flow"},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp of the last modification to the flow"},"lastExecutedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp of the last execution of the flow"},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow was created"},"resolvedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow was resolved (errors cleared)"},"deletedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow was soft deleted"},"free":{"type":"boolean","description":"Indicates if the flow is free or requires a premium subscription"},"_templateId":{"type":"string","format":"objectId","readOnly":true,"description":"Identifier for the template used to create this flow"},"externalId":{"type":"string","description":"External identifier associated with the flow"},"_sourceId":{"type":"string","format":"objectId","readOnly":true,"description":"Identifier for the source system of the flow"},"wizardState":{"type":"string","description":"Current state of the flow setup wizard"},"setupInProgress":{"type":"boolean","description":"Flag indicating if the flow setup is currently in progress"},"__startDateHelper":{"type":"string","description":"Internal helper field for managing the start date"},"__retryAtHelper":{"type":"string","description":"Internal helper field for managing retry timestamps"},"_exportId":{"type":"string","format":"objectId","readOnly":true,"description":"Legacy field - identifier for a single export (deprecated in favor of pageGenerators)"},"_importId":{"type":"string","format":"objectId","readOnly":true,"description":"Legacy field - identifier for a single import (deprecated in favor of pageProcessors)"}}}]},"ResourceResponse":{"type":"object","description":"Core response fields shared by all Celigo resources","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the resource.\n\nThe _id is used in:\n- API endpoints that operate on a specific resource (e.g., GET, PUT, DELETE)\n- References from other resources (e.g., flows that use this resource)\n- Job history and error tracking\n\nFormat: 24-character hexadecimal string\n"},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp indicating when the resource was initially created.\n\nThis read-only field is automatically set during resource creation and cannot\nbe modified. It provides an audit trail for when the resource was first added\nto the system, which can be useful for:\n\n- Resource lifecycle management\n- Audit and compliance reporting\n- Troubleshooting integration timelines\n- Identifying older resources that may need review\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix).\n"},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp indicating when the resource was most recently updated.\n\nThis read-only field is automatically updated whenever any property of the\nresource is modified. It provides an audit trail that can be used for:\n\n- Determining if a resource has changed since it was last reviewed\n- Monitoring configuration changes during troubleshooting\n- Implementing cache invalidation strategies\n- Synchronizing related resources based on modification time\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix)\nand will always be equal to or later than the createdAt timestamp.\n"},"deletedAt":{"type":["string","null"],"format":"date-time","readOnly":true,"description":"Timestamp indicating when the resource was marked for deletion.\n\nWhen this field is present and contains a valid timestamp, it indicates\nthat the resource has been soft-deleted (moved to the recycle bin) but not\nyet permanently removed from the system. This allows for recovery of\naccidentally deleted resources within a specified retention period.\n\nThe deletedAt timestamp enables:\n- Filtering deleted resources from active resource listings\n- Implementing time-based retention policies for permanent deletion\n- Tracking deletion events for audit and compliance purposes\n- Resource recovery workflows with clear timeframes\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix).\nWhen null or absent, the resource is considered active.\n"}},"required":["_id"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"422-unprocessable-entity":{"description":"Unprocessable entity. The request was well-formed but was unable to be followed due to semantic errors.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows":{"post":{"summary":"Create a flow","description":"Creates a new flow configuration that orchestrates data movement between systems.\n","operationId":"createFlow","tags":["Flows"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Request"}}}},"responses":{"201":{"description":"Flow created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Response"}}}},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"422":{"$ref":"#/components/responses/422-unprocessable-entity"}}}}}}
```

## Get a flow

> Returns the complete configuration of a specific flow.<br>

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"Response":{"type":"object","description":"Complete flow object as returned by the API","allOf":[{"$ref":"#/components/schemas/Request"},{"$ref":"#/components/schemas/ResourceResponse"},{"type":"object","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the flow"},"_userId":{"type":"string","format":"objectId","readOnly":true,"description":"Identifier of the user who owns the flow"},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp of the last modification to the flow"},"lastExecutedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp of the last execution of the flow"},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow was created"},"resolvedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow was resolved (errors cleared)"},"deletedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow was soft deleted"},"free":{"type":"boolean","description":"Indicates if the flow is free or requires a premium subscription"},"_templateId":{"type":"string","format":"objectId","readOnly":true,"description":"Identifier for the template used to create this flow"},"externalId":{"type":"string","description":"External identifier associated with the flow"},"_sourceId":{"type":"string","format":"objectId","readOnly":true,"description":"Identifier for the source system of the flow"},"wizardState":{"type":"string","description":"Current state of the flow setup wizard"},"setupInProgress":{"type":"boolean","description":"Flag indicating if the flow setup is currently in progress"},"__startDateHelper":{"type":"string","description":"Internal helper field for managing the start date"},"__retryAtHelper":{"type":"string","description":"Internal helper field for managing retry timestamps"},"_exportId":{"type":"string","format":"objectId","readOnly":true,"description":"Legacy field - identifier for a single export (deprecated in favor of pageGenerators)"},"_importId":{"type":"string","format":"objectId","readOnly":true,"description":"Legacy field - identifier for a single import (deprecated in favor of pageProcessors)"}}}]},"Request":{"type":"object","description":"Fields that can be sent when creating or updating a flow","properties":{"name":{"type":"string","description":"Descriptive identifier for the flow resource in human-readable format.\n\nThis string serves as the primary display name for the flow across the application UI and is used in:\n- API responses when listing flows\n- Job execution logs and monitoring dashboards\n- Flow builder UI components\n- Integration status reports\n\nWhile not required to be globally unique in the system, using descriptive, unique names is strongly recommended\nfor clarity when managing multiple integrations. The name should indicate the data flow direction and purpose.\n\nMaximum length: 255 characters\nAllowed characters: Letters, numbers, spaces, and basic punctuation\n"},"description":{"type":"string","description":"Optional free-text field that provides additional context about the flow's purpose and functionality.\n\nWhile not used for operational functionality in the API, this field serves several important purposes:\n- Helps document the business logic and data transformations applied\n- Provides context for other developers and administrators\n- Appears in the admin UI and flow listings for easier identification\n- Can be used by AI agents to better understand the flow's purpose when making recommendations\n\nBest practice is to include information about:\n- The source and destination systems\n- The type of data being synchronized\n- Any special business rules or transformations\n- Dependencies on other flows or systems\n- Run frequency and timing considerations\n\nMaximum length: 1000 characters\n"},"_integrationId":{"type":"string","format":"objectId","description":"Reference to the integration resource that this flow belongs to.\n\nThis field contains the unique identifier of an integration resource that must exist in the system.\nThe integration provides:\n- Logical grouping of related flows\n- Shared configuration and settings\n- Centralized monitoring and management\n- Common error handling patterns\n\nFormat: 24-character hexadecimal string\n"},"schedule":{"type":"string","description":"Cron expression that determines when the flow executes.\n\nThis field accepts Celigo 6-field cron expressions:\n- Format: \"second minute hour day-of-month month day-of-week\"\n- Second is always ? (no specific value)\n- Minute defaults to 5 for hourly+ schedules, or comma-separated list for sub-hourly\n- Hours use explicit comma-separated lists (NOT wildcards or step expressions)\n- Day-of-month is ? for most schedules\n- Month is * for every month\n- Day-of-week is * for every day, or specific days (0=Sun through 6=Sat)\n\nExamples:\n- \"? 0,15,30,45 * ? * *\" - Every 15 minutes\n- \"? 5 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23 ? * *\" - Every hour\n- \"? 5 0,4,8,12,16,20 ? * *\" - Every 4 hours\n- \"? 5 0 ? * *\" - Daily\n- \"? 5 9 ? * 1,2,3,4,5\" - Weekdays at 9 AM\n\nLeave empty for event-driven flows that are triggered by webhooks or other flows.\n"},"timezone":{"type":"string","description":"Timezone in which the schedule is interpreted.\n\nThis field specifies the timezone for the cron schedule:\n- Uses IANA timezone identifiers (e.g., \"America/New_York\")\n- Affects when scheduled flows execute\n- Important for daylight saving time handling\n- Defaults to UTC if not specified\n\nThe timezone ensures flows run at consistent local times regardless of:\n- Server location\n- Daylight saving time changes\n- Geographic distribution of systems\n"},"disabled":{"type":"boolean","description":"Controls whether the flow is active or disabled.\n\nWhen set to true:\n- Scheduled executions are suspended\n- The flow cannot be triggered manually or by events\n- Running jobs are allowed to complete\n- Configuration is preserved for future reactivation\n\nWhen set to false (default):\n- Flow executes according to its schedule\n- Manual and event triggers are processed\n- All configured processors and routers are active\n\nDEFAULT: true (flows are created in disabled state for safety)\n","default":true},"skipRetries":{"type":"boolean","description":"Controls whether failed executions should be retried.\n\nWhen set to true:\n- Failed jobs are not automatically retried\n- Errors are logged but no retry attempts are made\n- Useful for time-sensitive data or non-idempotent operations\n\nWhen set to false (default):\n- Failed jobs are retried according to the system retry policy\n- Exponential backoff is applied between retry attempts\n- Maximum retry attempts are determined by system configuration\n"},"pageGenerators":{"type":"array","description":"List of data sources that generate pages of records for the flow to process.\n\nPage generators are the starting points of a flow that:\n- Retrieve data from source systems via exports\n- Can run in parallel if configured\n- Generate pages of records (up to 5MB each)\n- Pass data to subsequent processors or routers\n\nEach generator can have its own schedule or inherit the flow's schedule.\n","items":{"$ref":"#/components/schemas/PageGenerator"}},"pageProcessors":{"type":"array","description":"List of processing steps that operate on data pages in sequence. Either routers or pageProcessors should be present in the flow configuration and not both.\n\nPage processors transform and route data through the flow:\n- Execute in the order defined\n- Can include exports (lookups), imports, or routers\n- Support error handling and conditional execution\n- May include response mapping for data enrichment\n","items":{"$ref":"#/components/schemas/PageProcessor"}},"routers":{"type":"array","description":"List of routing configurations that direct records to different branches. Either routers or pageProcessors should be present in the flow configuration and not both.\n\nRouters enable conditional processing by:\n- Evaluating records against defined criteria\n- Directing records to appropriate branches\n- Supporting complex business logic\n- Enabling parallel processing paths\n","items":{"$ref":"#/components/schemas/Router"}},"_runNextFlowIds":{"type":"array","description":"List of flow IDs to execute after this flow completes successfully.\n\nThis enables flow chaining where:\n- Dependent flows run automatically\n- Data pipelines can be orchestrated\n- Complex multi-step processes are coordinated\n- Success of this flow triggers the next flows\n","items":{"type":"string"}},"_runNextExportIds":{"type":"array","description":"List of export configurations to trigger after flow completion.\n\nThis field allows triggering specific exports in other flows:\n- Enables cross-flow dependencies\n- Supports selective data refreshes\n- Maintains loose coupling between flows\n","items":{"type":"object","properties":{"_flowId":{"type":"string","format":"objectId","description":"The flow containing the export to trigger"},"_exportId":{"type":"string","format":"objectId","description":"The specific export to execute"}}}},"settings":{"type":"object","description":"Custom configuration settings for the flow.\n\nThis object can contain:\n- Flow-specific parameters\n- Runtime configuration values\n- Feature flags or toggles\n- Custom business logic settings\n\nThe structure is flexible and determined by the flow's requirements.\n","additionalProperties":true},"_connectorId":{"type":"string","format":"objectId","description":"Reference to a connector template used by this flow.\n\nConnectors provide:\n- Pre-built integration templates\n- Standardized data mappings\n- Best practice configurations\n- Reusable integration patterns\n"},"runPageGeneratorsInParallel":{"type":"boolean","description":"Controls whether multiple page generators execute simultaneously.\n\nWhen set to true:\n- All page generators start at the same time\n- Improves throughput for independent data sources\n- Requires careful consideration of API rate limits\n\nWhen set to false (default):\n- Page generators execute sequentially\n- Safer for rate-limited APIs\n- Easier to debug and monitor\n"},"autoResolveMatchingTraceKeys":{"type":"boolean","description":"Enables automatic resolution of duplicate records based on trace keys.\n\nWhen set to true:\n- Records with matching trace keys are automatically resolved\n- Reduces manual intervention for known duplicates\n- Useful for idempotent operations\n\nWhen set to false (default):\n- Duplicate trace keys trigger error handling\n- Requires manual resolution\n- Provides more control over data integrity\n"},"isAbstract":{"type":"boolean","description":"Marks this flow as an abstract flow (multi-instance flow).\n\nAbstract flows define a reusable flow structure that cannot be executed directly.\nInstead, instance flows reference an abstract flow via _abstractFlowId and provide\noverrides to customize behavior per instance (different connections, schedules,\nhooks, etc.) while sharing the same flow graph.\n\nConstraints when isAbstract is true:\n- The flow cannot be triggered or run — only instance flows execute\n- Top-level pageProcessors are not allowed; all processing steps must be\n  inside routers[].branches[].pageProcessors\n- Cannot reference another abstract flow (_abstractFlowId is forbidden)\n- Cannot be set as a \"run next flow\" target\n- Cannot be unset to false while instance flows reference this flow\n- The overridesHelper field becomes available to declare which fields\n  are overridable by instances\n"},"_abstractFlowId":{"type":"string","format":"objectId","description":"Reference to an abstract flow that this instance flow inherits from.\n\nWhen specified, this flow becomes an instance flow:\n- It inherits the flow graph (pageGenerators, routers) from the abstract flow\n- The overrides object customizes connections, exports, imports, routers,\n  schedules, hooks, and other settings per instance\n- Instance flows cannot define their own pageGenerators, pageProcessors,\n  routers, or runPageGeneratorsInParallel\n- This field is immutable once set — it cannot be changed after creation\n- The referenced flow must exist and have isAbstract: true\n- Self-reference is not allowed\n\nAt runtime, the system merges the abstract flow configuration with the\ninstance flow overrides to produce the final executable flow configuration.\n"},"overrides":{"$ref":"#/components/schemas/Overrides"},"overridesHelper":{"$ref":"#/components/schemas/OverridesHelper"},"hidden":{"type":"boolean","description":"Controls visibility of the flow in user interfaces.\n\nWhen set to true:\n- Flow is hidden from standard UI views\n- Still executable and manageable via API\n- Useful for system or utility flows\n\nWhen set to false (default):\n- Flow appears in all standard UI views\n- Visible in flow lists and monitors\n"},"_flowGroupingId":{"type":"string","format":"objectId","description":"Identifier for grouping related flows together.\n\nFlow grouping enables:\n- Logical organization of related flows\n- Bulk operations on flow groups\n- Simplified monitoring and management\n- Visual grouping in UI\n"},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Reference to another flow for delta synchronization coordination.\n\nThis advanced feature:\n- Ensures this flow's delta stays behind the specified flow\n- Prevents race conditions in dependent data syncs\n- Maintains data consistency across related flows\n- Used for parent-child data relationships\n"},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Reference to a specific export for delta synchronization coordination.\n\nSimilar to _keepDeltaBehindFlowId but more granular:\n- Targets a specific export within a flow\n- Provides fine-grained control over delta timing\n- Ensures proper sequencing of dependent exports\n"},"aiDescription":{"type":"string","description":"AI-generated or user-provided description used by AI agents to understand the flow."},"aliases":{"type":"array","description":"Named aliases that map to specific resources within the flow.","items":{"type":"object","properties":{"alias":{"type":"string","description":"Alias name for the resource reference."},"_exportId":{"type":"string","format":"objectId","description":"Export referenced by this alias."},"_importId":{"type":"string","format":"objectId","description":"Import referenced by this alias."},"_flowId":{"type":"string","format":"objectId","description":"Flow referenced by this alias."},"_connectionId":{"type":"string","format":"objectId","description":"Connection referenced by this alias."}}}},"draft":{"type":"boolean","description":"Whether this flow is in draft mode and not yet published."},"draftExpiresAt":{"type":"string","format":"date-time","description":"Timestamp when the draft version of this flow expires."},"logging":{"type":"object","description":"Flow-level logging configuration.","properties":{"mode":{"type":"string","description":"Logging mode (e.g., off, on, debug)."},"debugUntil":{"type":"string","format":"date-time","description":"Timestamp until which debug-level logging is enabled."}}},"numInstances":{"type":"integer","description":"Number of instance flows derived from this abstract flow."},"preSave":{"type":"object","description":"Pre-save hook that runs a script before persisting flow changes.","properties":{"function":{"type":"string","description":"Function name to invoke in the pre-save script."},"_scriptId":{"type":"string","format":"objectId","description":"Script containing the pre-save function."}}},"settingsForm":{"type":"object","description":"Form definition used to collect flow-level settings from users.","additionalProperties":true}}},"PageGenerator":{"type":"object","description":"Configuration for a data source that generates pages of records for flow processing.\n\nPage generators are the entry points of a flow that retrieve data from source systems.\nThey can be scheduled independently or inherit the flow's schedule, and multiple generators\ncan run in parallel if configured.\n","properties":{"_exportId":{"type":"string","format":"objectId","description":"Reference to the export resource that retrieves data from the source system.\n\nThe export defines:\n- Connection to the source system\n- Query or API configuration\n- Data retrieval method (standard, delta, webhook, etc.)\n- Pagination and filtering rules\n\nFormat: 24-character hexadecimal string\n"},"schedule":{"type":"string","description":"Optional cron expression for this specific page generator.\n\nWhen specified:\n- Overrides the flow's main schedule for this generator\n- Allows different data sources to refresh at different intervals\n- Useful for sources with varying update frequencies\n\nWhen not specified:\n- Inherits the flow's schedule\n- Executes whenever the flow is triggered\n"},"skipRetries":{"type":"boolean","description":"Controls retry behavior for this specific page generator.\n\nWhen true:\n- Failed attempts are not retried\n- Errors are logged but flow may continue\n- Useful for non-critical or time-sensitive data\n\nWhen false (default):\n- Failed attempts are retried per system policy\n- Ensures data completeness\n"},"setupInProgress":{"type":"boolean","description":"Internal flag indicating if the generator configuration is being modified.\n\nThis is managed by the system and should not be set directly.\n"},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Reference to another flow for delta synchronization coordination.\n\nWhen specified:\n- This generator's delta timestamp stays behind the referenced flow\n- Prevents processing child records before parent records\n- Maintains referential integrity across flows\n"},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Reference to a specific export for delta synchronization coordination.\n\nMore granular than _keepDeltaBehindFlowId:\n- Targets a specific export's delta timestamp\n- Provides precise control over data dependencies\n- Useful for complex multi-source synchronization\n"},"__startDateHelper":{"type":"string","description":"Internal helper field for managing scheduled start dates"}},"required":["_exportId"]},"PageProcessor":{"type":"object","description":"Configuration for a processing step that operates on pages of data within a flow.\n\nPage processors can be exports (for lookups), imports (for data loading), or references\nto routers for conditional processing. They execute sequentially unless part of a router branch.\n","properties":{"type":{"type":"string","description":"Specifies the type of processor to determine which fields are relevant.\n\n- \"export\": Uses an export for data lookup/enrichment\n- \"import\": Sends data to a destination system\n","enum":["export","import"]},"_exportId":{"type":"string","format":"objectId","description":"Reference to an export resource used for data lookup or enrichment.\n\nRequired when type=\"export\". The export must be configured as a lookup\n(isLookup=true) to receive and process incoming records.\n\nCommon uses:\n- Retrieve additional details from a system\n- Validate data against a reference source\n- Enrich records with related information\n"},"_importId":{"type":"string","format":"objectId","description":"Reference to an import resource for sending data to a destination system.\n\nRequired when type=\"import\". The import defines:\n- Target system connection\n- Data mapping and transformation\n- Error handling and validation rules\n- Create/update logic\n"},"proceedOnFailure":{"type":"boolean","description":"Controls flow behavior when this processor encounters errors.\n\nWhen true:\n- Errors are logged but don't stop the flow\n- Subsequent processors continue execution\n- Failed records may be skipped\n\nWhen false (default):\n- Errors stop flow execution\n- No subsequent processors run\n- Maintains data integrity\n"},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"hooks":{"type":"object","description":"Custom code hooks for extending processor functionality","properties":{"postResponseMap":{"type":"object","description":"Hook executed after response mapping completes","properties":{"function":{"type":"string","description":"Function name to execute"},"_scriptId":{"type":"string","format":"objectId","description":"Reference to the script containing the function"}}}}},"setupInProgress":{"type":"boolean","description":"Internal flag indicating if the processor configuration is being modified.\n\nThis is managed by the system and should not be set directly.\n"}},"oneOf":[{"title":"Export processor","required":["type","_exportId"],"properties":{"_exportId":{"type":"string","format":"objectId","description":"Reference to an export resource used for data lookup or enrichment.\n\nRequired when type=\"export\". The export must be configured as a lookup\n(isLookup=true) to receive and process incoming records.\n\nCommon uses:\n- Retrieve additional details from a system\n- Validate data against a reference source\n- Enrich records with related information\n"}}},{"title":"Import processor","required":["type","_importId"],"properties":{"_importId":{"type":"string","format":"objectId","description":"Reference to an import resource for sending data to a destination system.\n\nRequired when type=\"import\". The import defines:\n- Target system connection\n- Data mapping and transformation\n- Error handling and validation rules\n- Create/update logic\n"}}}]},"ResponseMapping":{"type":"object","description":"Configuration for mapping data returned from lookups back to the original records.\n\nResponse mapping is used primarily with export processors (type=\"export\") to merge\nlookup results with the records being processed. This enables data enrichment workflows.\n","properties":{"fields":{"type":"object","description":"Field-level mapping configuration","properties":{"type":{"type":"array","description":"List of field mappings that define how to extract and map individual fields\nfrom the lookup response back to the original record.\n","items":{"type":"object","properties":{"extract":{"type":"string","description":"Path to extract data from the lookup response.\n\nUses dot notation to navigate nested objects in the response.\nCan reference arrays using index notation.\n"},"generate":{"type":"string","description":"Target field path where the extracted value will be stored.\n\nUses dot notation to specify where in the original record\nto place the extracted value.\n"},"_id":{"type":"boolean","description":"Internal identifier flag"}}}},"cLocked":{"type":"boolean","description":"Lock status preventing UI modifications.\n\nWhen true, the field mappings cannot be edited in the UI\nbut can still be modified via API.\n"}}},"lists":{"type":"object","description":"List/array mapping configuration","properties":{"type":{"type":"array","description":"List of array mappings for handling one-to-many relationships\nin lookup responses.\n","items":{"type":"object","properties":{"generate":{"type":"string","description":"Target array field where list data will be stored.\n\nThe specified field will be created as an array in the\noriginal record to hold the mapped list items.\n"},"fields":{"type":"array","description":"Field mappings within each list item.\n\nDefines how to map fields from each item in the response\narray to the corresponding item in the target array.\n","items":{"type":"object","properties":{"extract":{"type":"string","description":"Source field from each array item"},"generate":{"type":"string","description":"Target field in each array item"},"_id":{"type":"boolean","description":"Internal identifier flag"}}}},"_id":{"type":"boolean","description":"Internal identifier flag"}}}},"cLocked":{"type":"boolean","description":"Lock status preventing UI modifications.\n\nWhen true, the list mappings cannot be edited in the UI\nbut can still be modified via API.\n"}}}}},"Router":{"type":"object","description":"Configuration for conditional routing that directs records to different processing branches.\n\nRouters evaluate each record against defined criteria and route them to appropriate branches\nfor specialized processing. This enables complex business logic and conditional workflows.\n","properties":{"id":{"type":"string","description":"Unique identifier for this router within the flow.\n\nUsed to reference this router from page processors and for chaining routers.\nMust be unique within the flow's router collection.\n"},"name":{"type":"string","description":"Human-readable name for the router.\n\nDisplayed in the UI and logs to help identify the router's purpose.\n"},"routeRecordsTo":{"type":"string","description":"Strategy for routing records to branches.\n- \"first_matching_branch\": Routes to the first branch whose criteria match (most common)\n- \"all_matching_branches\": Routes to all branches whose criteria match (creates copies)\n","enum":["first_matching_branch","all_matching_branches"],"default":"first_matching_branch"},"routeRecordsUsing":{"type":"string","description":"Method used to evaluate routing criteria.\n\n- \"input_filters\": Uses declarative filter expressions\n- \"script\": Uses custom JavaScript for complex logic\n","enum":["input_filters","script"],"default":"input_filters"},"script":{"type":"object","description":"Script configuration when routeRecordsUsing=\"script\".\n\nEnables custom routing logic that can't be expressed with filters.\n","properties":{"_scriptId":{"type":"string","format":"objectId","description":"Reference to the script resource"},"function":{"type":"string","description":"Function name that returns the branch name for each record"}}},"branches":{"type":"array","description":"List of branches that define different processing paths.\n\nEach branch has its own criteria and processing steps. Records are evaluated\nagainst branch criteria in the order defined.\n","items":{"$ref":"#/components/schemas/Branch"}},"nextRouterId":{"type":"string","description":"Optional reference to another router to chain after this one.\n\nEnables sequential routing decisions where records pass through\nmultiple routers for complex branching logic.\n"}},"required":["branches"]},"Branch":{"type":"object","description":"Configuration for a single branch within a router that defines criteria and processing steps.\n\nEach branch represents a conditional path that records can take based on matching criteria.\nBranches are evaluated in order, and records are routed based on the router's strategy.\n","properties":{"name":{"type":"string","description":"Unique name for this branch within the router.\n\nUsed for:\n- Identification in logs and monitoring\n- Reference in custom routing scripts\n- Display in the UI\n\nShould be descriptive of the branch's purpose or criteria.\n"},"description":{"type":"string","description":"Optional description explaining the branch's purpose and criteria.\n\nHelps document:\n- What types of records this branch handles\n- Business logic or rules applied\n- Why this branch exists\n"},"inputFilter":{"type":"object","description":"Filter criteria that determines which records match this branch.\n\nOnly used when the router's routeRecordsUsing=\"inputFilter\".\nRecords matching these criteria will be routed to this branch.\n","properties":{"version":{"type":"string","description":"Version of the filter expression language"},"rules":{"type":"object","description":"Filter rules defining the matching criteria.\n\nThe structure depends on the version but typically includes\nlogical operators and field comparisons.\n","additionalProperties":true}}},"pageProcessors":{"type":"array","description":"List of processors that execute for records routed to this branch.\n\nThese processors:\n- Execute in sequence for records matching this branch\n- Can include exports, imports, or nested routers\n- Have the same structure as flow-level page processors\n- Continue until completion or error (unless proceedOnFailure is set)\n","items":{"$ref":"#/components/schemas/PageProcessor"}}},"required":["name"]},"Overrides":{"type":"object","description":"Configuration overrides for flows that inherit from abstract flows.\n\nWhen a flow inherits from an abstract flow template, this object allows selective\noverriding of inherited configuration while maintaining the base structure.\n","properties":{"name":{"type":"string","description":"Override for the flow's display name"},"description":{"type":"string","description":"Override for the flow's description"},"settings":{"type":"object","description":"Override for custom flow settings.\n\nAllows modifying specific settings while inheriting others from\nthe abstract flow template.\n","additionalProperties":true},"timezone":{"type":"string","description":"Override for the flow's schedule timezone"},"_runNextFlowIds":{"type":"array","description":"Override list of flows to trigger after completion","items":{"type":"string"}},"_runNextExportIds":{"type":"array","description":"Override list of exports to trigger after completion","items":{"type":"object","properties":{"_flowId":{"type":"string","description":"The flow containing the export"},"_exportId":{"type":"string","description":"The specific export to trigger"}}}},"__listenerIdsToIndex":{"type":"array","description":"Internal field for indexing listener configurations","items":{"type":"string"}},"connections":{"type":"array","description":"Override connection configurations for abstract flow connections.\n\nMaps abstract connection placeholders to concrete connection instances.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract connection being overridden"},"_id":{"type":"string","description":"Concrete connection ID to use instead"},"_borrowConcurrencyFromConnectionId":{"type":"string","description":"Optional connection to share concurrency limits with.\n\nUseful when multiple connections access the same system\nand need to share rate limiting.\n"}}}},"exports":{"type":"array","description":"Override configurations for exports in the abstract flow.\n\nAllows customizing export behavior while maintaining the flow structure.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract export being overridden"},"_id":{"type":"string","description":"Concrete export ID to use (if replacing entirely)"},"_connectionId":{"type":"string","description":"Override the connection used by this export"},"_keepDeltaBehindFlowId":{"type":"string","description":"Override delta synchronization settings"},"_keepDeltaBehindExportId":{"type":"string","description":"Override delta synchronization settings"},"schedule":{"type":"string","description":"Override the export's schedule"},"skipRetries":{"type":"boolean","description":"Override retry behavior"},"proceedOnFailure":{"type":"boolean","description":"Override error handling behavior"},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"pageSize":{"type":"integer","description":"Override page size for this export"},"dataURITemplate":{"type":"string","description":"Override URI template for error tracking"},"traceKeyTemplate":{"type":"string","description":"Override trace key generation"},"pathToMany":{"type":"string","description":"Override one-to-many path configuration"},"inputFilter":{"type":"object","description":"Override input filtering rules","properties":{"version":{"type":"string"},"rules":{"type":"object","additionalProperties":true}}},"groupByFields":{"type":"array","description":"Override grouping fields","items":{"type":"string"}},"test":{"type":"object","description":"Override test mode settings","properties":{"limit":{"type":"integer"}}},"delta":{"type":"object","description":"Override delta configuration","properties":{"dateField":{"type":"string"},"dateFormat":{"type":"string"},"startDate":{"type":"string"},"lagOffset":{"type":"integer"},"endDateField":{"type":"string"}}},"once":{"type":"object","description":"Override once export settings","properties":{"booleanField":{"type":"string"}}},"valueDelta":{"type":"object","description":"Override value delta settings","properties":{"exportedField":{"type":"string"},"pendingField":{"type":"string"}}},"webhook":{"type":"object","description":"Override webhook configuration","properties":{"token_crypt":{"type":"string"},"token_salt":{"type":"string"},"path":{"type":"string"},"key_crypt":{"type":"string"},"key_salt":{"type":"string"},"header":{"type":"string"},"username":{"type":"string"},"password_crypt":{"type":"string"},"password_salt":{"type":"string"},"successStatusCode":{"type":"integer"},"successBody":{"type":"string"},"successMediaType":{"type":"string"}}},"distributed":{"type":"object","description":"Override distributed processing settings","properties":{"bearerToken_crypt":{"type":"string"},"bearerToken_salt":{"type":"string"}}},"hooks":{"type":"object","description":"Override hook configurations"},"transform":{"type":"object","description":"Override transformation settings"},"parsers":{"type":"array","description":"Override parser configurations","items":{"type":"object"}},"filters":{"type":"object","description":"Override filter configurations"},"formSchema":{"type":"object","description":"Override form schema"},"preSaveSchema":{"type":"object","description":"Override pre-save configuration"},"settings":{"type":"object","description":"Override export-specific settings","additionalProperties":true},"idLockTemplate":{"type":"string","description":"Override ID lock template"}}}},"imports":{"type":"array","description":"Override configurations for imports in the abstract flow.\n\nSimilar structure to export overrides but for import resources.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract import being overridden"},"_connectionId":{"type":"string","description":"Override the connection used by this import"},"proceedOnFailure":{"type":"boolean","description":"Override error handling behavior"},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"idLockTemplate":{"type":"string"},"dataURITemplate":{"type":"string"},"pathToMany":{"type":"string"},"blobKeyPath":{"type":"string"},"filter":{"type":"object","additionalProperties":true},"traceKeyTemplate":{"type":"string"},"parsers":{"type":"array","items":{"type":"object"}},"hooks":{"type":"object","additionalProperties":true},"responseTransform":{"type":"object","additionalProperties":true},"mapping":{"type":"object","additionalProperties":true},"mappings":{"type":"array","items":{"type":"object"}},"lookups":{"type":"array","items":{"type":"object"}},"settingsForm":{"type":"object","additionalProperties":true},"preSave":{"type":"object","additionalProperties":true},"settings":{"type":"object","additionalProperties":true}}}},"routers":{"type":"array","description":"Override configurations for routers in the abstract flow.\n\nAllows customizing router behavior and branch configurations.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract router being overridden"},"name":{"type":"string","description":"Override router name"},"script":{"type":"object","description":"Override routing script","properties":{"_scriptId":{"type":"string"},"function":{"type":"string"}}},"branches":{"type":"array","description":"Override branch configurations","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract branch being overridden"},"name":{"type":"string"},"description":{"type":"string"},"inputFilter":{"type":"object","properties":{"version":{"type":"string"},"rules":{"type":"object","additionalProperties":true}}}}}}}}}}},"OverridesHelper":{"type":"object","description":"Metadata for abstract flows that declares which fields in the flow's connections,\nexports, imports, and routers are overridable by instance flows.\n\nOnly valid on abstract flows (isAbstract: true). The backend rejects this field\non non-abstract flows. Each entry references a component of the abstract flow by\nits ID and lists the field names that instance flows are allowed to override.\n","properties":{"fields":{"type":"array","description":"Flow-level field names that instance flows may override (e.g., \"schedule\", \"timezone\")","items":{"type":"string"}},"connections":{"type":"array","description":"Declares which connection-level fields are overridable per abstract flow connection.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the connection in the abstract flow"},"fields":{"type":"array","description":"Field names on this connection that instance flows may override","items":{"type":"string"}}}}},"exports":{"type":"array","description":"Declares which export-level fields are overridable per abstract flow export.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the export in the abstract flow"},"fields":{"type":"array","description":"Field names on this export that instance flows may override","items":{"type":"string"}}}}},"imports":{"type":"array","description":"Declares which import-level fields are overridable per abstract flow import.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the import in the abstract flow"},"fields":{"type":"array","description":"Field names on this import that instance flows may override","items":{"type":"string"}}}}},"routers":{"type":"array","description":"Declares which router-level and branch-level fields are overridable per abstract flow router.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the router in the abstract flow"},"fields":{"type":"array","description":"Field names on this router that instance flows may override","items":{"type":"string"}},"branches":{"type":"array","description":"Per-branch override declarations","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"Index or ID of the branch in the abstract flow router"},"fields":{"type":"array","description":"Field names on this branch that instance flows may override","items":{"type":"string"}}}}}}}}}},"ResourceResponse":{"type":"object","description":"Core response fields shared by all Celigo resources","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the resource.\n\nThe _id is used in:\n- API endpoints that operate on a specific resource (e.g., GET, PUT, DELETE)\n- References from other resources (e.g., flows that use this resource)\n- Job history and error tracking\n\nFormat: 24-character hexadecimal string\n"},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp indicating when the resource was initially created.\n\nThis read-only field is automatically set during resource creation and cannot\nbe modified. It provides an audit trail for when the resource was first added\nto the system, which can be useful for:\n\n- Resource lifecycle management\n- Audit and compliance reporting\n- Troubleshooting integration timelines\n- Identifying older resources that may need review\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix).\n"},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp indicating when the resource was most recently updated.\n\nThis read-only field is automatically updated whenever any property of the\nresource is modified. It provides an audit trail that can be used for:\n\n- Determining if a resource has changed since it was last reviewed\n- Monitoring configuration changes during troubleshooting\n- Implementing cache invalidation strategies\n- Synchronizing related resources based on modification time\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix)\nand will always be equal to or later than the createdAt timestamp.\n"},"deletedAt":{"type":["string","null"],"format":"date-time","readOnly":true,"description":"Timestamp indicating when the resource was marked for deletion.\n\nWhen this field is present and contains a valid timestamp, it indicates\nthat the resource has been soft-deleted (moved to the recycle bin) but not\nyet permanently removed from the system. This allows for recovery of\naccidentally deleted resources within a specified retention period.\n\nThe deletedAt timestamp enables:\n- Filtering deleted resources from active resource listings\n- Implementing time-based retention policies for permanent deletion\n- Tracking deletion events for audit and compliance purposes\n- Resource recovery workflows with clear timeframes\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix).\nWhen null or absent, the resource is considered active.\n"}},"required":["_id"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}":{"get":{"summary":"Get a flow","description":"Returns the complete configuration of a specific flow.\n","operationId":"getFlowById","tags":["Flows"],"parameters":[{"name":"_id","in":"path","description":"The unique identifier of the flow","required":true,"schema":{"type":"string","format":"objectId"}}],"responses":{"200":{"description":"Flow retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Response"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Update a flow

> Updates an existing flow with the provided configuration.\
> This is used for major updates to a flow's structure or behavior.<br>

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"Request":{"type":"object","description":"Fields that can be sent when creating or updating a flow","properties":{"name":{"type":"string","description":"Descriptive identifier for the flow resource in human-readable format.\n\nThis string serves as the primary display name for the flow across the application UI and is used in:\n- API responses when listing flows\n- Job execution logs and monitoring dashboards\n- Flow builder UI components\n- Integration status reports\n\nWhile not required to be globally unique in the system, using descriptive, unique names is strongly recommended\nfor clarity when managing multiple integrations. The name should indicate the data flow direction and purpose.\n\nMaximum length: 255 characters\nAllowed characters: Letters, numbers, spaces, and basic punctuation\n"},"description":{"type":"string","description":"Optional free-text field that provides additional context about the flow's purpose and functionality.\n\nWhile not used for operational functionality in the API, this field serves several important purposes:\n- Helps document the business logic and data transformations applied\n- Provides context for other developers and administrators\n- Appears in the admin UI and flow listings for easier identification\n- Can be used by AI agents to better understand the flow's purpose when making recommendations\n\nBest practice is to include information about:\n- The source and destination systems\n- The type of data being synchronized\n- Any special business rules or transformations\n- Dependencies on other flows or systems\n- Run frequency and timing considerations\n\nMaximum length: 1000 characters\n"},"_integrationId":{"type":"string","format":"objectId","description":"Reference to the integration resource that this flow belongs to.\n\nThis field contains the unique identifier of an integration resource that must exist in the system.\nThe integration provides:\n- Logical grouping of related flows\n- Shared configuration and settings\n- Centralized monitoring and management\n- Common error handling patterns\n\nFormat: 24-character hexadecimal string\n"},"schedule":{"type":"string","description":"Cron expression that determines when the flow executes.\n\nThis field accepts Celigo 6-field cron expressions:\n- Format: \"second minute hour day-of-month month day-of-week\"\n- Second is always ? (no specific value)\n- Minute defaults to 5 for hourly+ schedules, or comma-separated list for sub-hourly\n- Hours use explicit comma-separated lists (NOT wildcards or step expressions)\n- Day-of-month is ? for most schedules\n- Month is * for every month\n- Day-of-week is * for every day, or specific days (0=Sun through 6=Sat)\n\nExamples:\n- \"? 0,15,30,45 * ? * *\" - Every 15 minutes\n- \"? 5 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23 ? * *\" - Every hour\n- \"? 5 0,4,8,12,16,20 ? * *\" - Every 4 hours\n- \"? 5 0 ? * *\" - Daily\n- \"? 5 9 ? * 1,2,3,4,5\" - Weekdays at 9 AM\n\nLeave empty for event-driven flows that are triggered by webhooks or other flows.\n"},"timezone":{"type":"string","description":"Timezone in which the schedule is interpreted.\n\nThis field specifies the timezone for the cron schedule:\n- Uses IANA timezone identifiers (e.g., \"America/New_York\")\n- Affects when scheduled flows execute\n- Important for daylight saving time handling\n- Defaults to UTC if not specified\n\nThe timezone ensures flows run at consistent local times regardless of:\n- Server location\n- Daylight saving time changes\n- Geographic distribution of systems\n"},"disabled":{"type":"boolean","description":"Controls whether the flow is active or disabled.\n\nWhen set to true:\n- Scheduled executions are suspended\n- The flow cannot be triggered manually or by events\n- Running jobs are allowed to complete\n- Configuration is preserved for future reactivation\n\nWhen set to false (default):\n- Flow executes according to its schedule\n- Manual and event triggers are processed\n- All configured processors and routers are active\n\nDEFAULT: true (flows are created in disabled state for safety)\n","default":true},"skipRetries":{"type":"boolean","description":"Controls whether failed executions should be retried.\n\nWhen set to true:\n- Failed jobs are not automatically retried\n- Errors are logged but no retry attempts are made\n- Useful for time-sensitive data or non-idempotent operations\n\nWhen set to false (default):\n- Failed jobs are retried according to the system retry policy\n- Exponential backoff is applied between retry attempts\n- Maximum retry attempts are determined by system configuration\n"},"pageGenerators":{"type":"array","description":"List of data sources that generate pages of records for the flow to process.\n\nPage generators are the starting points of a flow that:\n- Retrieve data from source systems via exports\n- Can run in parallel if configured\n- Generate pages of records (up to 5MB each)\n- Pass data to subsequent processors or routers\n\nEach generator can have its own schedule or inherit the flow's schedule.\n","items":{"$ref":"#/components/schemas/PageGenerator"}},"pageProcessors":{"type":"array","description":"List of processing steps that operate on data pages in sequence. Either routers or pageProcessors should be present in the flow configuration and not both.\n\nPage processors transform and route data through the flow:\n- Execute in the order defined\n- Can include exports (lookups), imports, or routers\n- Support error handling and conditional execution\n- May include response mapping for data enrichment\n","items":{"$ref":"#/components/schemas/PageProcessor"}},"routers":{"type":"array","description":"List of routing configurations that direct records to different branches. Either routers or pageProcessors should be present in the flow configuration and not both.\n\nRouters enable conditional processing by:\n- Evaluating records against defined criteria\n- Directing records to appropriate branches\n- Supporting complex business logic\n- Enabling parallel processing paths\n","items":{"$ref":"#/components/schemas/Router"}},"_runNextFlowIds":{"type":"array","description":"List of flow IDs to execute after this flow completes successfully.\n\nThis enables flow chaining where:\n- Dependent flows run automatically\n- Data pipelines can be orchestrated\n- Complex multi-step processes are coordinated\n- Success of this flow triggers the next flows\n","items":{"type":"string"}},"_runNextExportIds":{"type":"array","description":"List of export configurations to trigger after flow completion.\n\nThis field allows triggering specific exports in other flows:\n- Enables cross-flow dependencies\n- Supports selective data refreshes\n- Maintains loose coupling between flows\n","items":{"type":"object","properties":{"_flowId":{"type":"string","format":"objectId","description":"The flow containing the export to trigger"},"_exportId":{"type":"string","format":"objectId","description":"The specific export to execute"}}}},"settings":{"type":"object","description":"Custom configuration settings for the flow.\n\nThis object can contain:\n- Flow-specific parameters\n- Runtime configuration values\n- Feature flags or toggles\n- Custom business logic settings\n\nThe structure is flexible and determined by the flow's requirements.\n","additionalProperties":true},"_connectorId":{"type":"string","format":"objectId","description":"Reference to a connector template used by this flow.\n\nConnectors provide:\n- Pre-built integration templates\n- Standardized data mappings\n- Best practice configurations\n- Reusable integration patterns\n"},"runPageGeneratorsInParallel":{"type":"boolean","description":"Controls whether multiple page generators execute simultaneously.\n\nWhen set to true:\n- All page generators start at the same time\n- Improves throughput for independent data sources\n- Requires careful consideration of API rate limits\n\nWhen set to false (default):\n- Page generators execute sequentially\n- Safer for rate-limited APIs\n- Easier to debug and monitor\n"},"autoResolveMatchingTraceKeys":{"type":"boolean","description":"Enables automatic resolution of duplicate records based on trace keys.\n\nWhen set to true:\n- Records with matching trace keys are automatically resolved\n- Reduces manual intervention for known duplicates\n- Useful for idempotent operations\n\nWhen set to false (default):\n- Duplicate trace keys trigger error handling\n- Requires manual resolution\n- Provides more control over data integrity\n"},"isAbstract":{"type":"boolean","description":"Marks this flow as an abstract flow (multi-instance flow).\n\nAbstract flows define a reusable flow structure that cannot be executed directly.\nInstead, instance flows reference an abstract flow via _abstractFlowId and provide\noverrides to customize behavior per instance (different connections, schedules,\nhooks, etc.) while sharing the same flow graph.\n\nConstraints when isAbstract is true:\n- The flow cannot be triggered or run — only instance flows execute\n- Top-level pageProcessors are not allowed; all processing steps must be\n  inside routers[].branches[].pageProcessors\n- Cannot reference another abstract flow (_abstractFlowId is forbidden)\n- Cannot be set as a \"run next flow\" target\n- Cannot be unset to false while instance flows reference this flow\n- The overridesHelper field becomes available to declare which fields\n  are overridable by instances\n"},"_abstractFlowId":{"type":"string","format":"objectId","description":"Reference to an abstract flow that this instance flow inherits from.\n\nWhen specified, this flow becomes an instance flow:\n- It inherits the flow graph (pageGenerators, routers) from the abstract flow\n- The overrides object customizes connections, exports, imports, routers,\n  schedules, hooks, and other settings per instance\n- Instance flows cannot define their own pageGenerators, pageProcessors,\n  routers, or runPageGeneratorsInParallel\n- This field is immutable once set — it cannot be changed after creation\n- The referenced flow must exist and have isAbstract: true\n- Self-reference is not allowed\n\nAt runtime, the system merges the abstract flow configuration with the\ninstance flow overrides to produce the final executable flow configuration.\n"},"overrides":{"$ref":"#/components/schemas/Overrides"},"overridesHelper":{"$ref":"#/components/schemas/OverridesHelper"},"hidden":{"type":"boolean","description":"Controls visibility of the flow in user interfaces.\n\nWhen set to true:\n- Flow is hidden from standard UI views\n- Still executable and manageable via API\n- Useful for system or utility flows\n\nWhen set to false (default):\n- Flow appears in all standard UI views\n- Visible in flow lists and monitors\n"},"_flowGroupingId":{"type":"string","format":"objectId","description":"Identifier for grouping related flows together.\n\nFlow grouping enables:\n- Logical organization of related flows\n- Bulk operations on flow groups\n- Simplified monitoring and management\n- Visual grouping in UI\n"},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Reference to another flow for delta synchronization coordination.\n\nThis advanced feature:\n- Ensures this flow's delta stays behind the specified flow\n- Prevents race conditions in dependent data syncs\n- Maintains data consistency across related flows\n- Used for parent-child data relationships\n"},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Reference to a specific export for delta synchronization coordination.\n\nSimilar to _keepDeltaBehindFlowId but more granular:\n- Targets a specific export within a flow\n- Provides fine-grained control over delta timing\n- Ensures proper sequencing of dependent exports\n"},"aiDescription":{"type":"string","description":"AI-generated or user-provided description used by AI agents to understand the flow."},"aliases":{"type":"array","description":"Named aliases that map to specific resources within the flow.","items":{"type":"object","properties":{"alias":{"type":"string","description":"Alias name for the resource reference."},"_exportId":{"type":"string","format":"objectId","description":"Export referenced by this alias."},"_importId":{"type":"string","format":"objectId","description":"Import referenced by this alias."},"_flowId":{"type":"string","format":"objectId","description":"Flow referenced by this alias."},"_connectionId":{"type":"string","format":"objectId","description":"Connection referenced by this alias."}}}},"draft":{"type":"boolean","description":"Whether this flow is in draft mode and not yet published."},"draftExpiresAt":{"type":"string","format":"date-time","description":"Timestamp when the draft version of this flow expires."},"logging":{"type":"object","description":"Flow-level logging configuration.","properties":{"mode":{"type":"string","description":"Logging mode (e.g., off, on, debug)."},"debugUntil":{"type":"string","format":"date-time","description":"Timestamp until which debug-level logging is enabled."}}},"numInstances":{"type":"integer","description":"Number of instance flows derived from this abstract flow."},"preSave":{"type":"object","description":"Pre-save hook that runs a script before persisting flow changes.","properties":{"function":{"type":"string","description":"Function name to invoke in the pre-save script."},"_scriptId":{"type":"string","format":"objectId","description":"Script containing the pre-save function."}}},"settingsForm":{"type":"object","description":"Form definition used to collect flow-level settings from users.","additionalProperties":true}}},"PageGenerator":{"type":"object","description":"Configuration for a data source that generates pages of records for flow processing.\n\nPage generators are the entry points of a flow that retrieve data from source systems.\nThey can be scheduled independently or inherit the flow's schedule, and multiple generators\ncan run in parallel if configured.\n","properties":{"_exportId":{"type":"string","format":"objectId","description":"Reference to the export resource that retrieves data from the source system.\n\nThe export defines:\n- Connection to the source system\n- Query or API configuration\n- Data retrieval method (standard, delta, webhook, etc.)\n- Pagination and filtering rules\n\nFormat: 24-character hexadecimal string\n"},"schedule":{"type":"string","description":"Optional cron expression for this specific page generator.\n\nWhen specified:\n- Overrides the flow's main schedule for this generator\n- Allows different data sources to refresh at different intervals\n- Useful for sources with varying update frequencies\n\nWhen not specified:\n- Inherits the flow's schedule\n- Executes whenever the flow is triggered\n"},"skipRetries":{"type":"boolean","description":"Controls retry behavior for this specific page generator.\n\nWhen true:\n- Failed attempts are not retried\n- Errors are logged but flow may continue\n- Useful for non-critical or time-sensitive data\n\nWhen false (default):\n- Failed attempts are retried per system policy\n- Ensures data completeness\n"},"setupInProgress":{"type":"boolean","description":"Internal flag indicating if the generator configuration is being modified.\n\nThis is managed by the system and should not be set directly.\n"},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Reference to another flow for delta synchronization coordination.\n\nWhen specified:\n- This generator's delta timestamp stays behind the referenced flow\n- Prevents processing child records before parent records\n- Maintains referential integrity across flows\n"},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Reference to a specific export for delta synchronization coordination.\n\nMore granular than _keepDeltaBehindFlowId:\n- Targets a specific export's delta timestamp\n- Provides precise control over data dependencies\n- Useful for complex multi-source synchronization\n"},"__startDateHelper":{"type":"string","description":"Internal helper field for managing scheduled start dates"}},"required":["_exportId"]},"PageProcessor":{"type":"object","description":"Configuration for a processing step that operates on pages of data within a flow.\n\nPage processors can be exports (for lookups), imports (for data loading), or references\nto routers for conditional processing. They execute sequentially unless part of a router branch.\n","properties":{"type":{"type":"string","description":"Specifies the type of processor to determine which fields are relevant.\n\n- \"export\": Uses an export for data lookup/enrichment\n- \"import\": Sends data to a destination system\n","enum":["export","import"]},"_exportId":{"type":"string","format":"objectId","description":"Reference to an export resource used for data lookup or enrichment.\n\nRequired when type=\"export\". The export must be configured as a lookup\n(isLookup=true) to receive and process incoming records.\n\nCommon uses:\n- Retrieve additional details from a system\n- Validate data against a reference source\n- Enrich records with related information\n"},"_importId":{"type":"string","format":"objectId","description":"Reference to an import resource for sending data to a destination system.\n\nRequired when type=\"import\". The import defines:\n- Target system connection\n- Data mapping and transformation\n- Error handling and validation rules\n- Create/update logic\n"},"proceedOnFailure":{"type":"boolean","description":"Controls flow behavior when this processor encounters errors.\n\nWhen true:\n- Errors are logged but don't stop the flow\n- Subsequent processors continue execution\n- Failed records may be skipped\n\nWhen false (default):\n- Errors stop flow execution\n- No subsequent processors run\n- Maintains data integrity\n"},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"hooks":{"type":"object","description":"Custom code hooks for extending processor functionality","properties":{"postResponseMap":{"type":"object","description":"Hook executed after response mapping completes","properties":{"function":{"type":"string","description":"Function name to execute"},"_scriptId":{"type":"string","format":"objectId","description":"Reference to the script containing the function"}}}}},"setupInProgress":{"type":"boolean","description":"Internal flag indicating if the processor configuration is being modified.\n\nThis is managed by the system and should not be set directly.\n"}},"oneOf":[{"title":"Export processor","required":["type","_exportId"],"properties":{"_exportId":{"type":"string","format":"objectId","description":"Reference to an export resource used for data lookup or enrichment.\n\nRequired when type=\"export\". The export must be configured as a lookup\n(isLookup=true) to receive and process incoming records.\n\nCommon uses:\n- Retrieve additional details from a system\n- Validate data against a reference source\n- Enrich records with related information\n"}}},{"title":"Import processor","required":["type","_importId"],"properties":{"_importId":{"type":"string","format":"objectId","description":"Reference to an import resource for sending data to a destination system.\n\nRequired when type=\"import\". The import defines:\n- Target system connection\n- Data mapping and transformation\n- Error handling and validation rules\n- Create/update logic\n"}}}]},"ResponseMapping":{"type":"object","description":"Configuration for mapping data returned from lookups back to the original records.\n\nResponse mapping is used primarily with export processors (type=\"export\") to merge\nlookup results with the records being processed. This enables data enrichment workflows.\n","properties":{"fields":{"type":"object","description":"Field-level mapping configuration","properties":{"type":{"type":"array","description":"List of field mappings that define how to extract and map individual fields\nfrom the lookup response back to the original record.\n","items":{"type":"object","properties":{"extract":{"type":"string","description":"Path to extract data from the lookup response.\n\nUses dot notation to navigate nested objects in the response.\nCan reference arrays using index notation.\n"},"generate":{"type":"string","description":"Target field path where the extracted value will be stored.\n\nUses dot notation to specify where in the original record\nto place the extracted value.\n"},"_id":{"type":"boolean","description":"Internal identifier flag"}}}},"cLocked":{"type":"boolean","description":"Lock status preventing UI modifications.\n\nWhen true, the field mappings cannot be edited in the UI\nbut can still be modified via API.\n"}}},"lists":{"type":"object","description":"List/array mapping configuration","properties":{"type":{"type":"array","description":"List of array mappings for handling one-to-many relationships\nin lookup responses.\n","items":{"type":"object","properties":{"generate":{"type":"string","description":"Target array field where list data will be stored.\n\nThe specified field will be created as an array in the\noriginal record to hold the mapped list items.\n"},"fields":{"type":"array","description":"Field mappings within each list item.\n\nDefines how to map fields from each item in the response\narray to the corresponding item in the target array.\n","items":{"type":"object","properties":{"extract":{"type":"string","description":"Source field from each array item"},"generate":{"type":"string","description":"Target field in each array item"},"_id":{"type":"boolean","description":"Internal identifier flag"}}}},"_id":{"type":"boolean","description":"Internal identifier flag"}}}},"cLocked":{"type":"boolean","description":"Lock status preventing UI modifications.\n\nWhen true, the list mappings cannot be edited in the UI\nbut can still be modified via API.\n"}}}}},"Router":{"type":"object","description":"Configuration for conditional routing that directs records to different processing branches.\n\nRouters evaluate each record against defined criteria and route them to appropriate branches\nfor specialized processing. This enables complex business logic and conditional workflows.\n","properties":{"id":{"type":"string","description":"Unique identifier for this router within the flow.\n\nUsed to reference this router from page processors and for chaining routers.\nMust be unique within the flow's router collection.\n"},"name":{"type":"string","description":"Human-readable name for the router.\n\nDisplayed in the UI and logs to help identify the router's purpose.\n"},"routeRecordsTo":{"type":"string","description":"Strategy for routing records to branches.\n- \"first_matching_branch\": Routes to the first branch whose criteria match (most common)\n- \"all_matching_branches\": Routes to all branches whose criteria match (creates copies)\n","enum":["first_matching_branch","all_matching_branches"],"default":"first_matching_branch"},"routeRecordsUsing":{"type":"string","description":"Method used to evaluate routing criteria.\n\n- \"input_filters\": Uses declarative filter expressions\n- \"script\": Uses custom JavaScript for complex logic\n","enum":["input_filters","script"],"default":"input_filters"},"script":{"type":"object","description":"Script configuration when routeRecordsUsing=\"script\".\n\nEnables custom routing logic that can't be expressed with filters.\n","properties":{"_scriptId":{"type":"string","format":"objectId","description":"Reference to the script resource"},"function":{"type":"string","description":"Function name that returns the branch name for each record"}}},"branches":{"type":"array","description":"List of branches that define different processing paths.\n\nEach branch has its own criteria and processing steps. Records are evaluated\nagainst branch criteria in the order defined.\n","items":{"$ref":"#/components/schemas/Branch"}},"nextRouterId":{"type":"string","description":"Optional reference to another router to chain after this one.\n\nEnables sequential routing decisions where records pass through\nmultiple routers for complex branching logic.\n"}},"required":["branches"]},"Branch":{"type":"object","description":"Configuration for a single branch within a router that defines criteria and processing steps.\n\nEach branch represents a conditional path that records can take based on matching criteria.\nBranches are evaluated in order, and records are routed based on the router's strategy.\n","properties":{"name":{"type":"string","description":"Unique name for this branch within the router.\n\nUsed for:\n- Identification in logs and monitoring\n- Reference in custom routing scripts\n- Display in the UI\n\nShould be descriptive of the branch's purpose or criteria.\n"},"description":{"type":"string","description":"Optional description explaining the branch's purpose and criteria.\n\nHelps document:\n- What types of records this branch handles\n- Business logic or rules applied\n- Why this branch exists\n"},"inputFilter":{"type":"object","description":"Filter criteria that determines which records match this branch.\n\nOnly used when the router's routeRecordsUsing=\"inputFilter\".\nRecords matching these criteria will be routed to this branch.\n","properties":{"version":{"type":"string","description":"Version of the filter expression language"},"rules":{"type":"object","description":"Filter rules defining the matching criteria.\n\nThe structure depends on the version but typically includes\nlogical operators and field comparisons.\n","additionalProperties":true}}},"pageProcessors":{"type":"array","description":"List of processors that execute for records routed to this branch.\n\nThese processors:\n- Execute in sequence for records matching this branch\n- Can include exports, imports, or nested routers\n- Have the same structure as flow-level page processors\n- Continue until completion or error (unless proceedOnFailure is set)\n","items":{"$ref":"#/components/schemas/PageProcessor"}}},"required":["name"]},"Overrides":{"type":"object","description":"Configuration overrides for flows that inherit from abstract flows.\n\nWhen a flow inherits from an abstract flow template, this object allows selective\noverriding of inherited configuration while maintaining the base structure.\n","properties":{"name":{"type":"string","description":"Override for the flow's display name"},"description":{"type":"string","description":"Override for the flow's description"},"settings":{"type":"object","description":"Override for custom flow settings.\n\nAllows modifying specific settings while inheriting others from\nthe abstract flow template.\n","additionalProperties":true},"timezone":{"type":"string","description":"Override for the flow's schedule timezone"},"_runNextFlowIds":{"type":"array","description":"Override list of flows to trigger after completion","items":{"type":"string"}},"_runNextExportIds":{"type":"array","description":"Override list of exports to trigger after completion","items":{"type":"object","properties":{"_flowId":{"type":"string","description":"The flow containing the export"},"_exportId":{"type":"string","description":"The specific export to trigger"}}}},"__listenerIdsToIndex":{"type":"array","description":"Internal field for indexing listener configurations","items":{"type":"string"}},"connections":{"type":"array","description":"Override connection configurations for abstract flow connections.\n\nMaps abstract connection placeholders to concrete connection instances.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract connection being overridden"},"_id":{"type":"string","description":"Concrete connection ID to use instead"},"_borrowConcurrencyFromConnectionId":{"type":"string","description":"Optional connection to share concurrency limits with.\n\nUseful when multiple connections access the same system\nand need to share rate limiting.\n"}}}},"exports":{"type":"array","description":"Override configurations for exports in the abstract flow.\n\nAllows customizing export behavior while maintaining the flow structure.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract export being overridden"},"_id":{"type":"string","description":"Concrete export ID to use (if replacing entirely)"},"_connectionId":{"type":"string","description":"Override the connection used by this export"},"_keepDeltaBehindFlowId":{"type":"string","description":"Override delta synchronization settings"},"_keepDeltaBehindExportId":{"type":"string","description":"Override delta synchronization settings"},"schedule":{"type":"string","description":"Override the export's schedule"},"skipRetries":{"type":"boolean","description":"Override retry behavior"},"proceedOnFailure":{"type":"boolean","description":"Override error handling behavior"},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"pageSize":{"type":"integer","description":"Override page size for this export"},"dataURITemplate":{"type":"string","description":"Override URI template for error tracking"},"traceKeyTemplate":{"type":"string","description":"Override trace key generation"},"pathToMany":{"type":"string","description":"Override one-to-many path configuration"},"inputFilter":{"type":"object","description":"Override input filtering rules","properties":{"version":{"type":"string"},"rules":{"type":"object","additionalProperties":true}}},"groupByFields":{"type":"array","description":"Override grouping fields","items":{"type":"string"}},"test":{"type":"object","description":"Override test mode settings","properties":{"limit":{"type":"integer"}}},"delta":{"type":"object","description":"Override delta configuration","properties":{"dateField":{"type":"string"},"dateFormat":{"type":"string"},"startDate":{"type":"string"},"lagOffset":{"type":"integer"},"endDateField":{"type":"string"}}},"once":{"type":"object","description":"Override once export settings","properties":{"booleanField":{"type":"string"}}},"valueDelta":{"type":"object","description":"Override value delta settings","properties":{"exportedField":{"type":"string"},"pendingField":{"type":"string"}}},"webhook":{"type":"object","description":"Override webhook configuration","properties":{"token_crypt":{"type":"string"},"token_salt":{"type":"string"},"path":{"type":"string"},"key_crypt":{"type":"string"},"key_salt":{"type":"string"},"header":{"type":"string"},"username":{"type":"string"},"password_crypt":{"type":"string"},"password_salt":{"type":"string"},"successStatusCode":{"type":"integer"},"successBody":{"type":"string"},"successMediaType":{"type":"string"}}},"distributed":{"type":"object","description":"Override distributed processing settings","properties":{"bearerToken_crypt":{"type":"string"},"bearerToken_salt":{"type":"string"}}},"hooks":{"type":"object","description":"Override hook configurations"},"transform":{"type":"object","description":"Override transformation settings"},"parsers":{"type":"array","description":"Override parser configurations","items":{"type":"object"}},"filters":{"type":"object","description":"Override filter configurations"},"formSchema":{"type":"object","description":"Override form schema"},"preSaveSchema":{"type":"object","description":"Override pre-save configuration"},"settings":{"type":"object","description":"Override export-specific settings","additionalProperties":true},"idLockTemplate":{"type":"string","description":"Override ID lock template"}}}},"imports":{"type":"array","description":"Override configurations for imports in the abstract flow.\n\nSimilar structure to export overrides but for import resources.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract import being overridden"},"_connectionId":{"type":"string","description":"Override the connection used by this import"},"proceedOnFailure":{"type":"boolean","description":"Override error handling behavior"},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"idLockTemplate":{"type":"string"},"dataURITemplate":{"type":"string"},"pathToMany":{"type":"string"},"blobKeyPath":{"type":"string"},"filter":{"type":"object","additionalProperties":true},"traceKeyTemplate":{"type":"string"},"parsers":{"type":"array","items":{"type":"object"}},"hooks":{"type":"object","additionalProperties":true},"responseTransform":{"type":"object","additionalProperties":true},"mapping":{"type":"object","additionalProperties":true},"mappings":{"type":"array","items":{"type":"object"}},"lookups":{"type":"array","items":{"type":"object"}},"settingsForm":{"type":"object","additionalProperties":true},"preSave":{"type":"object","additionalProperties":true},"settings":{"type":"object","additionalProperties":true}}}},"routers":{"type":"array","description":"Override configurations for routers in the abstract flow.\n\nAllows customizing router behavior and branch configurations.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract router being overridden"},"name":{"type":"string","description":"Override router name"},"script":{"type":"object","description":"Override routing script","properties":{"_scriptId":{"type":"string"},"function":{"type":"string"}}},"branches":{"type":"array","description":"Override branch configurations","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract branch being overridden"},"name":{"type":"string"},"description":{"type":"string"},"inputFilter":{"type":"object","properties":{"version":{"type":"string"},"rules":{"type":"object","additionalProperties":true}}}}}}}}}}},"OverridesHelper":{"type":"object","description":"Metadata for abstract flows that declares which fields in the flow's connections,\nexports, imports, and routers are overridable by instance flows.\n\nOnly valid on abstract flows (isAbstract: true). The backend rejects this field\non non-abstract flows. Each entry references a component of the abstract flow by\nits ID and lists the field names that instance flows are allowed to override.\n","properties":{"fields":{"type":"array","description":"Flow-level field names that instance flows may override (e.g., \"schedule\", \"timezone\")","items":{"type":"string"}},"connections":{"type":"array","description":"Declares which connection-level fields are overridable per abstract flow connection.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the connection in the abstract flow"},"fields":{"type":"array","description":"Field names on this connection that instance flows may override","items":{"type":"string"}}}}},"exports":{"type":"array","description":"Declares which export-level fields are overridable per abstract flow export.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the export in the abstract flow"},"fields":{"type":"array","description":"Field names on this export that instance flows may override","items":{"type":"string"}}}}},"imports":{"type":"array","description":"Declares which import-level fields are overridable per abstract flow import.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the import in the abstract flow"},"fields":{"type":"array","description":"Field names on this import that instance flows may override","items":{"type":"string"}}}}},"routers":{"type":"array","description":"Declares which router-level and branch-level fields are overridable per abstract flow router.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the router in the abstract flow"},"fields":{"type":"array","description":"Field names on this router that instance flows may override","items":{"type":"string"}},"branches":{"type":"array","description":"Per-branch override declarations","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"Index or ID of the branch in the abstract flow router"},"fields":{"type":"array","description":"Field names on this branch that instance flows may override","items":{"type":"string"}}}}}}}}}},"Response":{"type":"object","description":"Complete flow object as returned by the API","allOf":[{"$ref":"#/components/schemas/Request"},{"$ref":"#/components/schemas/ResourceResponse"},{"type":"object","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the flow"},"_userId":{"type":"string","format":"objectId","readOnly":true,"description":"Identifier of the user who owns the flow"},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp of the last modification to the flow"},"lastExecutedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp of the last execution of the flow"},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow was created"},"resolvedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow was resolved (errors cleared)"},"deletedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow was soft deleted"},"free":{"type":"boolean","description":"Indicates if the flow is free or requires a premium subscription"},"_templateId":{"type":"string","format":"objectId","readOnly":true,"description":"Identifier for the template used to create this flow"},"externalId":{"type":"string","description":"External identifier associated with the flow"},"_sourceId":{"type":"string","format":"objectId","readOnly":true,"description":"Identifier for the source system of the flow"},"wizardState":{"type":"string","description":"Current state of the flow setup wizard"},"setupInProgress":{"type":"boolean","description":"Flag indicating if the flow setup is currently in progress"},"__startDateHelper":{"type":"string","description":"Internal helper field for managing the start date"},"__retryAtHelper":{"type":"string","description":"Internal helper field for managing retry timestamps"},"_exportId":{"type":"string","format":"objectId","readOnly":true,"description":"Legacy field - identifier for a single export (deprecated in favor of pageGenerators)"},"_importId":{"type":"string","format":"objectId","readOnly":true,"description":"Legacy field - identifier for a single import (deprecated in favor of pageProcessors)"}}}]},"ResourceResponse":{"type":"object","description":"Core response fields shared by all Celigo resources","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the resource.\n\nThe _id is used in:\n- API endpoints that operate on a specific resource (e.g., GET, PUT, DELETE)\n- References from other resources (e.g., flows that use this resource)\n- Job history and error tracking\n\nFormat: 24-character hexadecimal string\n"},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp indicating when the resource was initially created.\n\nThis read-only field is automatically set during resource creation and cannot\nbe modified. It provides an audit trail for when the resource was first added\nto the system, which can be useful for:\n\n- Resource lifecycle management\n- Audit and compliance reporting\n- Troubleshooting integration timelines\n- Identifying older resources that may need review\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix).\n"},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp indicating when the resource was most recently updated.\n\nThis read-only field is automatically updated whenever any property of the\nresource is modified. It provides an audit trail that can be used for:\n\n- Determining if a resource has changed since it was last reviewed\n- Monitoring configuration changes during troubleshooting\n- Implementing cache invalidation strategies\n- Synchronizing related resources based on modification time\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix)\nand will always be equal to or later than the createdAt timestamp.\n"},"deletedAt":{"type":["string","null"],"format":"date-time","readOnly":true,"description":"Timestamp indicating when the resource was marked for deletion.\n\nWhen this field is present and contains a valid timestamp, it indicates\nthat the resource has been soft-deleted (moved to the recycle bin) but not\nyet permanently removed from the system. This allows for recovery of\naccidentally deleted resources within a specified retention period.\n\nThe deletedAt timestamp enables:\n- Filtering deleted resources from active resource listings\n- Implementing time-based retention policies for permanent deletion\n- Tracking deletion events for audit and compliance purposes\n- Resource recovery workflows with clear timeframes\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix).\nWhen null or absent, the resource is considered active.\n"}},"required":["_id"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422-unprocessable-entity":{"description":"Unprocessable entity. The request was well-formed but was unable to be followed due to semantic errors.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}":{"put":{"summary":"Update a flow","description":"Updates an existing flow with the provided configuration.\nThis is used for major updates to a flow's structure or behavior.\n","operationId":"updateFlow","tags":["Flows"],"parameters":[{"name":"_id","in":"path","description":"The unique identifier of the flow","required":true,"schema":{"type":"string","format":"objectId"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Request"}}}},"responses":{"200":{"description":"Flow updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Response"}}}},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"},"422":{"$ref":"#/components/responses/422-unprocessable-entity"}}}}}}
```

## Delete a flow

> Deletes a flow. The flow is soft-deleted and retained in the recycle bin for\
> 30 days before permanent removal. Scheduled executions are stopped and any\
> running jobs will be cancelled.<br>

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}}},"paths":{"/v1/flows/{_id}":{"delete":{"summary":"Delete a flow","description":"Deletes a flow. The flow is soft-deleted and retained in the recycle bin for\n30 days before permanent removal. Scheduled executions are stopped and any\nrunning jobs will be cancelled.\n","operationId":"deleteFlow","tags":["Flows"],"parameters":[{"name":"_id","in":"path","description":"The unique identifier of the flow","required":true,"schema":{"type":"string","format":"objectId"}}],"responses":{"204":{"description":"Flow deleted successfully"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Patch a flow

> Partially updates a flow using a JSON Patch document (RFC 6902).\
> Only the \`replace\` operation is supported, and only on the following\
> whitelisted paths:\
> \
> \| Path | Description |\
> \|------|-------------|\
> \| \`/name\` | Flow display name |\
> \| \`/description\` | Flow description |\
> \| \`/disabled\` | Enable or disable the flow (boolean) |\
> \| \`/logging/debugUntil\` | Debug logging expiry (ISO-8601, max 1 hour from now) |\
> \| \`/logging/mode\` | Logging mode |\
> \| \`/runPageGeneratorsInParallel\` | Run page generators in parallel (boolean) |\
> \| \`/aiDescription\` | AI-generated description object |\
> \| \`/schedule/frequency\` | Schedule frequency |\
> \| \`/schedule/startDate\` | Schedule start date |\
> \| \`/schedule/endDate\` | Schedule end date |\
> \| \`/schedule/days\` | Schedule days |\
> \| \`/schedule/cron\` | Cron expression |\
> \
> All other paths are rejected with \`422\`.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"JsonPatchRequest":{"type":"array","description":"A JSON Patch document (RFC 6902). Send an array of patch\noperations. Only the `replace` operation is supported, and only\non whitelisted fields — all other paths are rejected with 422.","minItems":1,"items":{"$ref":"#/components/schemas/JsonPatchOperation"}},"JsonPatchOperation":{"type":"object","description":"A single JSON Patch operation (RFC 6902).","required":["op","path"],"properties":{"op":{"type":"string","enum":["replace"],"description":"The operation to perform. Only `replace` is supported."},"path":{"type":"string","description":"JSON Pointer (RFC 6901) to the field to patch. Only\nwhitelisted paths are accepted — unlisted paths return\n`422` with `\"<path> is not a whitelisted property\"`."},"value":{"description":"The new value to set at the given path."}}},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422-unprocessable-entity":{"description":"Unprocessable entity. The request was well-formed but was unable to be followed due to semantic errors.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}":{"patch":{"summary":"Patch a flow","description":"Partially updates a flow using a JSON Patch document (RFC 6902).\nOnly the `replace` operation is supported, and only on the following\nwhitelisted paths:\n\n| Path | Description |\n|------|-------------|\n| `/name` | Flow display name |\n| `/description` | Flow description |\n| `/disabled` | Enable or disable the flow (boolean) |\n| `/logging/debugUntil` | Debug logging expiry (ISO-8601, max 1 hour from now) |\n| `/logging/mode` | Logging mode |\n| `/runPageGeneratorsInParallel` | Run page generators in parallel (boolean) |\n| `/aiDescription` | AI-generated description object |\n| `/schedule/frequency` | Schedule frequency |\n| `/schedule/startDate` | Schedule start date |\n| `/schedule/endDate` | Schedule end date |\n| `/schedule/days` | Schedule days |\n| `/schedule/cron` | Cron expression |\n\nAll other paths are rejected with `422`.","operationId":"patchFlow","tags":["Flows"],"parameters":[{"name":"_id","in":"path","description":"The unique identifier of the flow","required":true,"schema":{"type":"string","format":"objectId"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonPatchRequest"}}}},"responses":{"204":{"description":"Flow patched successfully"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"},"422":{"$ref":"#/components/responses/422-unprocessable-entity"}}}}}}
```

## Clone a flow

> Creates a copy of an existing flow.\
> Supports optionally remapping referenced connections (via connectionMap) and/or attaching\
> the cloned flow to a specific integration (via \_integrationId).<br>

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"CloneRequest":{"type":"object","description":"Request body for cloning a flow.","properties":{"name":{"type":"string","description":"Optional name for the cloned resource. If omitted, the server may generate a default clone name."},"_integrationId":{"type":"string","format":"objectId","description":"Optional integration id to attach the cloned flow to."},"connectionMap":{"type":"object","description":"Optional mapping of original connection ids to replacement connection ids.\nKeys are source connection ids on the original resource; values are target connection ids.\n","additionalProperties":{"type":"string"}}},"additionalProperties":true},"CloneResponse":{"description":"Response body for a clone operation. Some clone endpoints return the cloned resource, while others may return a list of related created resources.","oneOf":[{"$ref":"#/components/schemas/Response"},{"type":"array","items":{"type":"object","properties":{"model":{"type":"string","description":"Model name of the created resource (e.g., Flow, Export, Import)."},"_id":{"type":"string","format":"objectId","description":"Unique id of the created resource."},"name":{"type":"string","description":"Optional name of the created resource."}},"required":["_id"]}}]},"Response":{"type":"object","description":"Complete flow object as returned by the API","allOf":[{"$ref":"#/components/schemas/Request"},{"$ref":"#/components/schemas/ResourceResponse"},{"type":"object","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the flow"},"_userId":{"type":"string","format":"objectId","readOnly":true,"description":"Identifier of the user who owns the flow"},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp of the last modification to the flow"},"lastExecutedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp of the last execution of the flow"},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow was created"},"resolvedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow was resolved (errors cleared)"},"deletedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow was soft deleted"},"free":{"type":"boolean","description":"Indicates if the flow is free or requires a premium subscription"},"_templateId":{"type":"string","format":"objectId","readOnly":true,"description":"Identifier for the template used to create this flow"},"externalId":{"type":"string","description":"External identifier associated with the flow"},"_sourceId":{"type":"string","format":"objectId","readOnly":true,"description":"Identifier for the source system of the flow"},"wizardState":{"type":"string","description":"Current state of the flow setup wizard"},"setupInProgress":{"type":"boolean","description":"Flag indicating if the flow setup is currently in progress"},"__startDateHelper":{"type":"string","description":"Internal helper field for managing the start date"},"__retryAtHelper":{"type":"string","description":"Internal helper field for managing retry timestamps"},"_exportId":{"type":"string","format":"objectId","readOnly":true,"description":"Legacy field - identifier for a single export (deprecated in favor of pageGenerators)"},"_importId":{"type":"string","format":"objectId","readOnly":true,"description":"Legacy field - identifier for a single import (deprecated in favor of pageProcessors)"}}}]},"Request":{"type":"object","description":"Fields that can be sent when creating or updating a flow","properties":{"name":{"type":"string","description":"Descriptive identifier for the flow resource in human-readable format.\n\nThis string serves as the primary display name for the flow across the application UI and is used in:\n- API responses when listing flows\n- Job execution logs and monitoring dashboards\n- Flow builder UI components\n- Integration status reports\n\nWhile not required to be globally unique in the system, using descriptive, unique names is strongly recommended\nfor clarity when managing multiple integrations. The name should indicate the data flow direction and purpose.\n\nMaximum length: 255 characters\nAllowed characters: Letters, numbers, spaces, and basic punctuation\n"},"description":{"type":"string","description":"Optional free-text field that provides additional context about the flow's purpose and functionality.\n\nWhile not used for operational functionality in the API, this field serves several important purposes:\n- Helps document the business logic and data transformations applied\n- Provides context for other developers and administrators\n- Appears in the admin UI and flow listings for easier identification\n- Can be used by AI agents to better understand the flow's purpose when making recommendations\n\nBest practice is to include information about:\n- The source and destination systems\n- The type of data being synchronized\n- Any special business rules or transformations\n- Dependencies on other flows or systems\n- Run frequency and timing considerations\n\nMaximum length: 1000 characters\n"},"_integrationId":{"type":"string","format":"objectId","description":"Reference to the integration resource that this flow belongs to.\n\nThis field contains the unique identifier of an integration resource that must exist in the system.\nThe integration provides:\n- Logical grouping of related flows\n- Shared configuration and settings\n- Centralized monitoring and management\n- Common error handling patterns\n\nFormat: 24-character hexadecimal string\n"},"schedule":{"type":"string","description":"Cron expression that determines when the flow executes.\n\nThis field accepts Celigo 6-field cron expressions:\n- Format: \"second minute hour day-of-month month day-of-week\"\n- Second is always ? (no specific value)\n- Minute defaults to 5 for hourly+ schedules, or comma-separated list for sub-hourly\n- Hours use explicit comma-separated lists (NOT wildcards or step expressions)\n- Day-of-month is ? for most schedules\n- Month is * for every month\n- Day-of-week is * for every day, or specific days (0=Sun through 6=Sat)\n\nExamples:\n- \"? 0,15,30,45 * ? * *\" - Every 15 minutes\n- \"? 5 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23 ? * *\" - Every hour\n- \"? 5 0,4,8,12,16,20 ? * *\" - Every 4 hours\n- \"? 5 0 ? * *\" - Daily\n- \"? 5 9 ? * 1,2,3,4,5\" - Weekdays at 9 AM\n\nLeave empty for event-driven flows that are triggered by webhooks or other flows.\n"},"timezone":{"type":"string","description":"Timezone in which the schedule is interpreted.\n\nThis field specifies the timezone for the cron schedule:\n- Uses IANA timezone identifiers (e.g., \"America/New_York\")\n- Affects when scheduled flows execute\n- Important for daylight saving time handling\n- Defaults to UTC if not specified\n\nThe timezone ensures flows run at consistent local times regardless of:\n- Server location\n- Daylight saving time changes\n- Geographic distribution of systems\n"},"disabled":{"type":"boolean","description":"Controls whether the flow is active or disabled.\n\nWhen set to true:\n- Scheduled executions are suspended\n- The flow cannot be triggered manually or by events\n- Running jobs are allowed to complete\n- Configuration is preserved for future reactivation\n\nWhen set to false (default):\n- Flow executes according to its schedule\n- Manual and event triggers are processed\n- All configured processors and routers are active\n\nDEFAULT: true (flows are created in disabled state for safety)\n","default":true},"skipRetries":{"type":"boolean","description":"Controls whether failed executions should be retried.\n\nWhen set to true:\n- Failed jobs are not automatically retried\n- Errors are logged but no retry attempts are made\n- Useful for time-sensitive data or non-idempotent operations\n\nWhen set to false (default):\n- Failed jobs are retried according to the system retry policy\n- Exponential backoff is applied between retry attempts\n- Maximum retry attempts are determined by system configuration\n"},"pageGenerators":{"type":"array","description":"List of data sources that generate pages of records for the flow to process.\n\nPage generators are the starting points of a flow that:\n- Retrieve data from source systems via exports\n- Can run in parallel if configured\n- Generate pages of records (up to 5MB each)\n- Pass data to subsequent processors or routers\n\nEach generator can have its own schedule or inherit the flow's schedule.\n","items":{"$ref":"#/components/schemas/PageGenerator"}},"pageProcessors":{"type":"array","description":"List of processing steps that operate on data pages in sequence. Either routers or pageProcessors should be present in the flow configuration and not both.\n\nPage processors transform and route data through the flow:\n- Execute in the order defined\n- Can include exports (lookups), imports, or routers\n- Support error handling and conditional execution\n- May include response mapping for data enrichment\n","items":{"$ref":"#/components/schemas/PageProcessor"}},"routers":{"type":"array","description":"List of routing configurations that direct records to different branches. Either routers or pageProcessors should be present in the flow configuration and not both.\n\nRouters enable conditional processing by:\n- Evaluating records against defined criteria\n- Directing records to appropriate branches\n- Supporting complex business logic\n- Enabling parallel processing paths\n","items":{"$ref":"#/components/schemas/Router"}},"_runNextFlowIds":{"type":"array","description":"List of flow IDs to execute after this flow completes successfully.\n\nThis enables flow chaining where:\n- Dependent flows run automatically\n- Data pipelines can be orchestrated\n- Complex multi-step processes are coordinated\n- Success of this flow triggers the next flows\n","items":{"type":"string"}},"_runNextExportIds":{"type":"array","description":"List of export configurations to trigger after flow completion.\n\nThis field allows triggering specific exports in other flows:\n- Enables cross-flow dependencies\n- Supports selective data refreshes\n- Maintains loose coupling between flows\n","items":{"type":"object","properties":{"_flowId":{"type":"string","format":"objectId","description":"The flow containing the export to trigger"},"_exportId":{"type":"string","format":"objectId","description":"The specific export to execute"}}}},"settings":{"type":"object","description":"Custom configuration settings for the flow.\n\nThis object can contain:\n- Flow-specific parameters\n- Runtime configuration values\n- Feature flags or toggles\n- Custom business logic settings\n\nThe structure is flexible and determined by the flow's requirements.\n","additionalProperties":true},"_connectorId":{"type":"string","format":"objectId","description":"Reference to a connector template used by this flow.\n\nConnectors provide:\n- Pre-built integration templates\n- Standardized data mappings\n- Best practice configurations\n- Reusable integration patterns\n"},"runPageGeneratorsInParallel":{"type":"boolean","description":"Controls whether multiple page generators execute simultaneously.\n\nWhen set to true:\n- All page generators start at the same time\n- Improves throughput for independent data sources\n- Requires careful consideration of API rate limits\n\nWhen set to false (default):\n- Page generators execute sequentially\n- Safer for rate-limited APIs\n- Easier to debug and monitor\n"},"autoResolveMatchingTraceKeys":{"type":"boolean","description":"Enables automatic resolution of duplicate records based on trace keys.\n\nWhen set to true:\n- Records with matching trace keys are automatically resolved\n- Reduces manual intervention for known duplicates\n- Useful for idempotent operations\n\nWhen set to false (default):\n- Duplicate trace keys trigger error handling\n- Requires manual resolution\n- Provides more control over data integrity\n"},"isAbstract":{"type":"boolean","description":"Marks this flow as an abstract flow (multi-instance flow).\n\nAbstract flows define a reusable flow structure that cannot be executed directly.\nInstead, instance flows reference an abstract flow via _abstractFlowId and provide\noverrides to customize behavior per instance (different connections, schedules,\nhooks, etc.) while sharing the same flow graph.\n\nConstraints when isAbstract is true:\n- The flow cannot be triggered or run — only instance flows execute\n- Top-level pageProcessors are not allowed; all processing steps must be\n  inside routers[].branches[].pageProcessors\n- Cannot reference another abstract flow (_abstractFlowId is forbidden)\n- Cannot be set as a \"run next flow\" target\n- Cannot be unset to false while instance flows reference this flow\n- The overridesHelper field becomes available to declare which fields\n  are overridable by instances\n"},"_abstractFlowId":{"type":"string","format":"objectId","description":"Reference to an abstract flow that this instance flow inherits from.\n\nWhen specified, this flow becomes an instance flow:\n- It inherits the flow graph (pageGenerators, routers) from the abstract flow\n- The overrides object customizes connections, exports, imports, routers,\n  schedules, hooks, and other settings per instance\n- Instance flows cannot define their own pageGenerators, pageProcessors,\n  routers, or runPageGeneratorsInParallel\n- This field is immutable once set — it cannot be changed after creation\n- The referenced flow must exist and have isAbstract: true\n- Self-reference is not allowed\n\nAt runtime, the system merges the abstract flow configuration with the\ninstance flow overrides to produce the final executable flow configuration.\n"},"overrides":{"$ref":"#/components/schemas/Overrides"},"overridesHelper":{"$ref":"#/components/schemas/OverridesHelper"},"hidden":{"type":"boolean","description":"Controls visibility of the flow in user interfaces.\n\nWhen set to true:\n- Flow is hidden from standard UI views\n- Still executable and manageable via API\n- Useful for system or utility flows\n\nWhen set to false (default):\n- Flow appears in all standard UI views\n- Visible in flow lists and monitors\n"},"_flowGroupingId":{"type":"string","format":"objectId","description":"Identifier for grouping related flows together.\n\nFlow grouping enables:\n- Logical organization of related flows\n- Bulk operations on flow groups\n- Simplified monitoring and management\n- Visual grouping in UI\n"},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Reference to another flow for delta synchronization coordination.\n\nThis advanced feature:\n- Ensures this flow's delta stays behind the specified flow\n- Prevents race conditions in dependent data syncs\n- Maintains data consistency across related flows\n- Used for parent-child data relationships\n"},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Reference to a specific export for delta synchronization coordination.\n\nSimilar to _keepDeltaBehindFlowId but more granular:\n- Targets a specific export within a flow\n- Provides fine-grained control over delta timing\n- Ensures proper sequencing of dependent exports\n"},"aiDescription":{"type":"string","description":"AI-generated or user-provided description used by AI agents to understand the flow."},"aliases":{"type":"array","description":"Named aliases that map to specific resources within the flow.","items":{"type":"object","properties":{"alias":{"type":"string","description":"Alias name for the resource reference."},"_exportId":{"type":"string","format":"objectId","description":"Export referenced by this alias."},"_importId":{"type":"string","format":"objectId","description":"Import referenced by this alias."},"_flowId":{"type":"string","format":"objectId","description":"Flow referenced by this alias."},"_connectionId":{"type":"string","format":"objectId","description":"Connection referenced by this alias."}}}},"draft":{"type":"boolean","description":"Whether this flow is in draft mode and not yet published."},"draftExpiresAt":{"type":"string","format":"date-time","description":"Timestamp when the draft version of this flow expires."},"logging":{"type":"object","description":"Flow-level logging configuration.","properties":{"mode":{"type":"string","description":"Logging mode (e.g., off, on, debug)."},"debugUntil":{"type":"string","format":"date-time","description":"Timestamp until which debug-level logging is enabled."}}},"numInstances":{"type":"integer","description":"Number of instance flows derived from this abstract flow."},"preSave":{"type":"object","description":"Pre-save hook that runs a script before persisting flow changes.","properties":{"function":{"type":"string","description":"Function name to invoke in the pre-save script."},"_scriptId":{"type":"string","format":"objectId","description":"Script containing the pre-save function."}}},"settingsForm":{"type":"object","description":"Form definition used to collect flow-level settings from users.","additionalProperties":true}}},"PageGenerator":{"type":"object","description":"Configuration for a data source that generates pages of records for flow processing.\n\nPage generators are the entry points of a flow that retrieve data from source systems.\nThey can be scheduled independently or inherit the flow's schedule, and multiple generators\ncan run in parallel if configured.\n","properties":{"_exportId":{"type":"string","format":"objectId","description":"Reference to the export resource that retrieves data from the source system.\n\nThe export defines:\n- Connection to the source system\n- Query or API configuration\n- Data retrieval method (standard, delta, webhook, etc.)\n- Pagination and filtering rules\n\nFormat: 24-character hexadecimal string\n"},"schedule":{"type":"string","description":"Optional cron expression for this specific page generator.\n\nWhen specified:\n- Overrides the flow's main schedule for this generator\n- Allows different data sources to refresh at different intervals\n- Useful for sources with varying update frequencies\n\nWhen not specified:\n- Inherits the flow's schedule\n- Executes whenever the flow is triggered\n"},"skipRetries":{"type":"boolean","description":"Controls retry behavior for this specific page generator.\n\nWhen true:\n- Failed attempts are not retried\n- Errors are logged but flow may continue\n- Useful for non-critical or time-sensitive data\n\nWhen false (default):\n- Failed attempts are retried per system policy\n- Ensures data completeness\n"},"setupInProgress":{"type":"boolean","description":"Internal flag indicating if the generator configuration is being modified.\n\nThis is managed by the system and should not be set directly.\n"},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Reference to another flow for delta synchronization coordination.\n\nWhen specified:\n- This generator's delta timestamp stays behind the referenced flow\n- Prevents processing child records before parent records\n- Maintains referential integrity across flows\n"},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Reference to a specific export for delta synchronization coordination.\n\nMore granular than _keepDeltaBehindFlowId:\n- Targets a specific export's delta timestamp\n- Provides precise control over data dependencies\n- Useful for complex multi-source synchronization\n"},"__startDateHelper":{"type":"string","description":"Internal helper field for managing scheduled start dates"}},"required":["_exportId"]},"PageProcessor":{"type":"object","description":"Configuration for a processing step that operates on pages of data within a flow.\n\nPage processors can be exports (for lookups), imports (for data loading), or references\nto routers for conditional processing. They execute sequentially unless part of a router branch.\n","properties":{"type":{"type":"string","description":"Specifies the type of processor to determine which fields are relevant.\n\n- \"export\": Uses an export for data lookup/enrichment\n- \"import\": Sends data to a destination system\n","enum":["export","import"]},"_exportId":{"type":"string","format":"objectId","description":"Reference to an export resource used for data lookup or enrichment.\n\nRequired when type=\"export\". The export must be configured as a lookup\n(isLookup=true) to receive and process incoming records.\n\nCommon uses:\n- Retrieve additional details from a system\n- Validate data against a reference source\n- Enrich records with related information\n"},"_importId":{"type":"string","format":"objectId","description":"Reference to an import resource for sending data to a destination system.\n\nRequired when type=\"import\". The import defines:\n- Target system connection\n- Data mapping and transformation\n- Error handling and validation rules\n- Create/update logic\n"},"proceedOnFailure":{"type":"boolean","description":"Controls flow behavior when this processor encounters errors.\n\nWhen true:\n- Errors are logged but don't stop the flow\n- Subsequent processors continue execution\n- Failed records may be skipped\n\nWhen false (default):\n- Errors stop flow execution\n- No subsequent processors run\n- Maintains data integrity\n"},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"hooks":{"type":"object","description":"Custom code hooks for extending processor functionality","properties":{"postResponseMap":{"type":"object","description":"Hook executed after response mapping completes","properties":{"function":{"type":"string","description":"Function name to execute"},"_scriptId":{"type":"string","format":"objectId","description":"Reference to the script containing the function"}}}}},"setupInProgress":{"type":"boolean","description":"Internal flag indicating if the processor configuration is being modified.\n\nThis is managed by the system and should not be set directly.\n"}},"oneOf":[{"title":"Export processor","required":["type","_exportId"],"properties":{"_exportId":{"type":"string","format":"objectId","description":"Reference to an export resource used for data lookup or enrichment.\n\nRequired when type=\"export\". The export must be configured as a lookup\n(isLookup=true) to receive and process incoming records.\n\nCommon uses:\n- Retrieve additional details from a system\n- Validate data against a reference source\n- Enrich records with related information\n"}}},{"title":"Import processor","required":["type","_importId"],"properties":{"_importId":{"type":"string","format":"objectId","description":"Reference to an import resource for sending data to a destination system.\n\nRequired when type=\"import\". The import defines:\n- Target system connection\n- Data mapping and transformation\n- Error handling and validation rules\n- Create/update logic\n"}}}]},"ResponseMapping":{"type":"object","description":"Configuration for mapping data returned from lookups back to the original records.\n\nResponse mapping is used primarily with export processors (type=\"export\") to merge\nlookup results with the records being processed. This enables data enrichment workflows.\n","properties":{"fields":{"type":"object","description":"Field-level mapping configuration","properties":{"type":{"type":"array","description":"List of field mappings that define how to extract and map individual fields\nfrom the lookup response back to the original record.\n","items":{"type":"object","properties":{"extract":{"type":"string","description":"Path to extract data from the lookup response.\n\nUses dot notation to navigate nested objects in the response.\nCan reference arrays using index notation.\n"},"generate":{"type":"string","description":"Target field path where the extracted value will be stored.\n\nUses dot notation to specify where in the original record\nto place the extracted value.\n"},"_id":{"type":"boolean","description":"Internal identifier flag"}}}},"cLocked":{"type":"boolean","description":"Lock status preventing UI modifications.\n\nWhen true, the field mappings cannot be edited in the UI\nbut can still be modified via API.\n"}}},"lists":{"type":"object","description":"List/array mapping configuration","properties":{"type":{"type":"array","description":"List of array mappings for handling one-to-many relationships\nin lookup responses.\n","items":{"type":"object","properties":{"generate":{"type":"string","description":"Target array field where list data will be stored.\n\nThe specified field will be created as an array in the\noriginal record to hold the mapped list items.\n"},"fields":{"type":"array","description":"Field mappings within each list item.\n\nDefines how to map fields from each item in the response\narray to the corresponding item in the target array.\n","items":{"type":"object","properties":{"extract":{"type":"string","description":"Source field from each array item"},"generate":{"type":"string","description":"Target field in each array item"},"_id":{"type":"boolean","description":"Internal identifier flag"}}}},"_id":{"type":"boolean","description":"Internal identifier flag"}}}},"cLocked":{"type":"boolean","description":"Lock status preventing UI modifications.\n\nWhen true, the list mappings cannot be edited in the UI\nbut can still be modified via API.\n"}}}}},"Router":{"type":"object","description":"Configuration for conditional routing that directs records to different processing branches.\n\nRouters evaluate each record against defined criteria and route them to appropriate branches\nfor specialized processing. This enables complex business logic and conditional workflows.\n","properties":{"id":{"type":"string","description":"Unique identifier for this router within the flow.\n\nUsed to reference this router from page processors and for chaining routers.\nMust be unique within the flow's router collection.\n"},"name":{"type":"string","description":"Human-readable name for the router.\n\nDisplayed in the UI and logs to help identify the router's purpose.\n"},"routeRecordsTo":{"type":"string","description":"Strategy for routing records to branches.\n- \"first_matching_branch\": Routes to the first branch whose criteria match (most common)\n- \"all_matching_branches\": Routes to all branches whose criteria match (creates copies)\n","enum":["first_matching_branch","all_matching_branches"],"default":"first_matching_branch"},"routeRecordsUsing":{"type":"string","description":"Method used to evaluate routing criteria.\n\n- \"input_filters\": Uses declarative filter expressions\n- \"script\": Uses custom JavaScript for complex logic\n","enum":["input_filters","script"],"default":"input_filters"},"script":{"type":"object","description":"Script configuration when routeRecordsUsing=\"script\".\n\nEnables custom routing logic that can't be expressed with filters.\n","properties":{"_scriptId":{"type":"string","format":"objectId","description":"Reference to the script resource"},"function":{"type":"string","description":"Function name that returns the branch name for each record"}}},"branches":{"type":"array","description":"List of branches that define different processing paths.\n\nEach branch has its own criteria and processing steps. Records are evaluated\nagainst branch criteria in the order defined.\n","items":{"$ref":"#/components/schemas/Branch"}},"nextRouterId":{"type":"string","description":"Optional reference to another router to chain after this one.\n\nEnables sequential routing decisions where records pass through\nmultiple routers for complex branching logic.\n"}},"required":["branches"]},"Branch":{"type":"object","description":"Configuration for a single branch within a router that defines criteria and processing steps.\n\nEach branch represents a conditional path that records can take based on matching criteria.\nBranches are evaluated in order, and records are routed based on the router's strategy.\n","properties":{"name":{"type":"string","description":"Unique name for this branch within the router.\n\nUsed for:\n- Identification in logs and monitoring\n- Reference in custom routing scripts\n- Display in the UI\n\nShould be descriptive of the branch's purpose or criteria.\n"},"description":{"type":"string","description":"Optional description explaining the branch's purpose and criteria.\n\nHelps document:\n- What types of records this branch handles\n- Business logic or rules applied\n- Why this branch exists\n"},"inputFilter":{"type":"object","description":"Filter criteria that determines which records match this branch.\n\nOnly used when the router's routeRecordsUsing=\"inputFilter\".\nRecords matching these criteria will be routed to this branch.\n","properties":{"version":{"type":"string","description":"Version of the filter expression language"},"rules":{"type":"object","description":"Filter rules defining the matching criteria.\n\nThe structure depends on the version but typically includes\nlogical operators and field comparisons.\n","additionalProperties":true}}},"pageProcessors":{"type":"array","description":"List of processors that execute for records routed to this branch.\n\nThese processors:\n- Execute in sequence for records matching this branch\n- Can include exports, imports, or nested routers\n- Have the same structure as flow-level page processors\n- Continue until completion or error (unless proceedOnFailure is set)\n","items":{"$ref":"#/components/schemas/PageProcessor"}}},"required":["name"]},"Overrides":{"type":"object","description":"Configuration overrides for flows that inherit from abstract flows.\n\nWhen a flow inherits from an abstract flow template, this object allows selective\noverriding of inherited configuration while maintaining the base structure.\n","properties":{"name":{"type":"string","description":"Override for the flow's display name"},"description":{"type":"string","description":"Override for the flow's description"},"settings":{"type":"object","description":"Override for custom flow settings.\n\nAllows modifying specific settings while inheriting others from\nthe abstract flow template.\n","additionalProperties":true},"timezone":{"type":"string","description":"Override for the flow's schedule timezone"},"_runNextFlowIds":{"type":"array","description":"Override list of flows to trigger after completion","items":{"type":"string"}},"_runNextExportIds":{"type":"array","description":"Override list of exports to trigger after completion","items":{"type":"object","properties":{"_flowId":{"type":"string","description":"The flow containing the export"},"_exportId":{"type":"string","description":"The specific export to trigger"}}}},"__listenerIdsToIndex":{"type":"array","description":"Internal field for indexing listener configurations","items":{"type":"string"}},"connections":{"type":"array","description":"Override connection configurations for abstract flow connections.\n\nMaps abstract connection placeholders to concrete connection instances.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract connection being overridden"},"_id":{"type":"string","description":"Concrete connection ID to use instead"},"_borrowConcurrencyFromConnectionId":{"type":"string","description":"Optional connection to share concurrency limits with.\n\nUseful when multiple connections access the same system\nand need to share rate limiting.\n"}}}},"exports":{"type":"array","description":"Override configurations for exports in the abstract flow.\n\nAllows customizing export behavior while maintaining the flow structure.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract export being overridden"},"_id":{"type":"string","description":"Concrete export ID to use (if replacing entirely)"},"_connectionId":{"type":"string","description":"Override the connection used by this export"},"_keepDeltaBehindFlowId":{"type":"string","description":"Override delta synchronization settings"},"_keepDeltaBehindExportId":{"type":"string","description":"Override delta synchronization settings"},"schedule":{"type":"string","description":"Override the export's schedule"},"skipRetries":{"type":"boolean","description":"Override retry behavior"},"proceedOnFailure":{"type":"boolean","description":"Override error handling behavior"},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"pageSize":{"type":"integer","description":"Override page size for this export"},"dataURITemplate":{"type":"string","description":"Override URI template for error tracking"},"traceKeyTemplate":{"type":"string","description":"Override trace key generation"},"pathToMany":{"type":"string","description":"Override one-to-many path configuration"},"inputFilter":{"type":"object","description":"Override input filtering rules","properties":{"version":{"type":"string"},"rules":{"type":"object","additionalProperties":true}}},"groupByFields":{"type":"array","description":"Override grouping fields","items":{"type":"string"}},"test":{"type":"object","description":"Override test mode settings","properties":{"limit":{"type":"integer"}}},"delta":{"type":"object","description":"Override delta configuration","properties":{"dateField":{"type":"string"},"dateFormat":{"type":"string"},"startDate":{"type":"string"},"lagOffset":{"type":"integer"},"endDateField":{"type":"string"}}},"once":{"type":"object","description":"Override once export settings","properties":{"booleanField":{"type":"string"}}},"valueDelta":{"type":"object","description":"Override value delta settings","properties":{"exportedField":{"type":"string"},"pendingField":{"type":"string"}}},"webhook":{"type":"object","description":"Override webhook configuration","properties":{"token_crypt":{"type":"string"},"token_salt":{"type":"string"},"path":{"type":"string"},"key_crypt":{"type":"string"},"key_salt":{"type":"string"},"header":{"type":"string"},"username":{"type":"string"},"password_crypt":{"type":"string"},"password_salt":{"type":"string"},"successStatusCode":{"type":"integer"},"successBody":{"type":"string"},"successMediaType":{"type":"string"}}},"distributed":{"type":"object","description":"Override distributed processing settings","properties":{"bearerToken_crypt":{"type":"string"},"bearerToken_salt":{"type":"string"}}},"hooks":{"type":"object","description":"Override hook configurations"},"transform":{"type":"object","description":"Override transformation settings"},"parsers":{"type":"array","description":"Override parser configurations","items":{"type":"object"}},"filters":{"type":"object","description":"Override filter configurations"},"formSchema":{"type":"object","description":"Override form schema"},"preSaveSchema":{"type":"object","description":"Override pre-save configuration"},"settings":{"type":"object","description":"Override export-specific settings","additionalProperties":true},"idLockTemplate":{"type":"string","description":"Override ID lock template"}}}},"imports":{"type":"array","description":"Override configurations for imports in the abstract flow.\n\nSimilar structure to export overrides but for import resources.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract import being overridden"},"_connectionId":{"type":"string","description":"Override the connection used by this import"},"proceedOnFailure":{"type":"boolean","description":"Override error handling behavior"},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"idLockTemplate":{"type":"string"},"dataURITemplate":{"type":"string"},"pathToMany":{"type":"string"},"blobKeyPath":{"type":"string"},"filter":{"type":"object","additionalProperties":true},"traceKeyTemplate":{"type":"string"},"parsers":{"type":"array","items":{"type":"object"}},"hooks":{"type":"object","additionalProperties":true},"responseTransform":{"type":"object","additionalProperties":true},"mapping":{"type":"object","additionalProperties":true},"mappings":{"type":"array","items":{"type":"object"}},"lookups":{"type":"array","items":{"type":"object"}},"settingsForm":{"type":"object","additionalProperties":true},"preSave":{"type":"object","additionalProperties":true},"settings":{"type":"object","additionalProperties":true}}}},"routers":{"type":"array","description":"Override configurations for routers in the abstract flow.\n\nAllows customizing router behavior and branch configurations.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract router being overridden"},"name":{"type":"string","description":"Override router name"},"script":{"type":"object","description":"Override routing script","properties":{"_scriptId":{"type":"string"},"function":{"type":"string"}}},"branches":{"type":"array","description":"Override branch configurations","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the abstract branch being overridden"},"name":{"type":"string"},"description":{"type":"string"},"inputFilter":{"type":"object","properties":{"version":{"type":"string"},"rules":{"type":"object","additionalProperties":true}}}}}}}}}}},"OverridesHelper":{"type":"object","description":"Metadata for abstract flows that declares which fields in the flow's connections,\nexports, imports, and routers are overridable by instance flows.\n\nOnly valid on abstract flows (isAbstract: true). The backend rejects this field\non non-abstract flows. Each entry references a component of the abstract flow by\nits ID and lists the field names that instance flows are allowed to override.\n","properties":{"fields":{"type":"array","description":"Flow-level field names that instance flows may override (e.g., \"schedule\", \"timezone\")","items":{"type":"string"}},"connections":{"type":"array","description":"Declares which connection-level fields are overridable per abstract flow connection.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the connection in the abstract flow"},"fields":{"type":"array","description":"Field names on this connection that instance flows may override","items":{"type":"string"}}}}},"exports":{"type":"array","description":"Declares which export-level fields are overridable per abstract flow export.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the export in the abstract flow"},"fields":{"type":"array","description":"Field names on this export that instance flows may override","items":{"type":"string"}}}}},"imports":{"type":"array","description":"Declares which import-level fields are overridable per abstract flow import.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the import in the abstract flow"},"fields":{"type":"array","description":"Field names on this import that instance flows may override","items":{"type":"string"}}}}},"routers":{"type":"array","description":"Declares which router-level and branch-level fields are overridable per abstract flow router.\n","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"ID of the router in the abstract flow"},"fields":{"type":"array","description":"Field names on this router that instance flows may override","items":{"type":"string"}},"branches":{"type":"array","description":"Per-branch override declarations","items":{"type":"object","properties":{"_abstractId":{"type":"string","description":"Index or ID of the branch in the abstract flow router"},"fields":{"type":"array","description":"Field names on this branch that instance flows may override","items":{"type":"string"}}}}}}}}}},"ResourceResponse":{"type":"object","description":"Core response fields shared by all Celigo resources","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the resource.\n\nThe _id is used in:\n- API endpoints that operate on a specific resource (e.g., GET, PUT, DELETE)\n- References from other resources (e.g., flows that use this resource)\n- Job history and error tracking\n\nFormat: 24-character hexadecimal string\n"},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp indicating when the resource was initially created.\n\nThis read-only field is automatically set during resource creation and cannot\nbe modified. It provides an audit trail for when the resource was first added\nto the system, which can be useful for:\n\n- Resource lifecycle management\n- Audit and compliance reporting\n- Troubleshooting integration timelines\n- Identifying older resources that may need review\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix).\n"},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp indicating when the resource was most recently updated.\n\nThis read-only field is automatically updated whenever any property of the\nresource is modified. It provides an audit trail that can be used for:\n\n- Determining if a resource has changed since it was last reviewed\n- Monitoring configuration changes during troubleshooting\n- Implementing cache invalidation strategies\n- Synchronizing related resources based on modification time\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix)\nand will always be equal to or later than the createdAt timestamp.\n"},"deletedAt":{"type":["string","null"],"format":"date-time","readOnly":true,"description":"Timestamp indicating when the resource was marked for deletion.\n\nWhen this field is present and contains a valid timestamp, it indicates\nthat the resource has been soft-deleted (moved to the recycle bin) but not\nyet permanently removed from the system. This allows for recovery of\naccidentally deleted resources within a specified retention period.\n\nThe deletedAt timestamp enables:\n- Filtering deleted resources from active resource listings\n- Implementing time-based retention policies for permanent deletion\n- Tracking deletion events for audit and compliance purposes\n- Resource recovery workflows with clear timeframes\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix).\nWhen null or absent, the resource is considered active.\n"}},"required":["_id"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422-unprocessable-entity":{"description":"Unprocessable entity. The request was well-formed but was unable to be followed due to semantic errors.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/clone":{"post":{"summary":"Clone a flow","description":"Creates a copy of an existing flow.\nSupports optionally remapping referenced connections (via connectionMap) and/or attaching\nthe cloned flow to a specific integration (via _integrationId).\n","operationId":"cloneFlow","tags":["Flows"],"parameters":[{"name":"_id","in":"path","description":"The unique identifier of the flow to clone","required":true,"schema":{"type":"string","format":"objectId"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CloneRequest"}}}},"responses":{"200":{"description":"Flow cloned successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CloneResponse"}}}},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"},"422":{"$ref":"#/components/responses/422-unprocessable-entity"}}}}}}
```

## Preview cloning a flow

> Returns a preview of the resources that would be created by cloning the specified flow.\
> The response includes the target flow and all transitive dependencies — connections,\
> exports, imports, scripts, async helpers, and lookup caches referenced by the flow.\
> No resources are created by this endpoint.<br>

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"ClonePreviewResponse":{"type":"object","description":"Preview of the resources that would be created by a clone operation.\nEach object in the `objects` array represents a resource that will be\ncloned, including the target resource and all transitive dependencies\n(connections, scripts, exports, imports, etc.).\n","properties":{"objects":{"type":"array","description":"List of resources that would be created by the clone. Always includes\nthe target resource and may include transitive dependencies such as\nconnections, scripts, exports, imports, async helpers, and lookup caches.\n","items":{"type":"object","properties":{"model":{"type":"string","description":"The model type of the resource. Observed values include\nAsyncHelper, Connection, Export, Flow, Import, Integration,\nLookupCache, and Script.\n"},"doc":{"type":"object","description":"The full resource document that would be created by the clone.","additionalProperties":true}},"required":["model","doc"]}},"stackRequired":{"type":"boolean","description":"Whether the clone requires a stack (connector-level) environment to proceed."},"_stackId":{"type":["string","null"],"description":"The stack id associated with the resource, or null if no stack is involved."}},"required":["objects","stackRequired","_stackId"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/clone/preview":{"get":{"summary":"Preview cloning a flow","description":"Returns a preview of the resources that would be created by cloning the specified flow.\nThe response includes the target flow and all transitive dependencies — connections,\nexports, imports, scripts, async helpers, and lookup caches referenced by the flow.\nNo resources are created by this endpoint.\n","operationId":"previewCloneFlow","tags":["Flows"],"parameters":[{"name":"_id","in":"path","description":"The unique identifier of the flow to preview cloning","required":true,"schema":{"type":"string","format":"objectId"}}],"responses":{"200":{"description":"Clone preview retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClonePreviewResponse"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Get a flow's descendant resources

> Returns the full resource objects for every import, export, and tool referenced by the flow.\
> This is a convenience endpoint that resolves the flow's entire dependency tree in a single\
> call — equivalent to reading the flow config and then fetching each referenced resource\
> individually, but without the N+1 round-trips.\
> \
> AI guidance:\
> \- Use this to inspect a flow's full wiring (connections, adaptors, mappings) without having to\
> &#x20; walk \`pageGenerators\[].{\_exportId}\` and \`pageProcessors\[].{\_importId}\` manually.\
> \- The arrays mirror the resource shapes returned by \`GET /v1/imports/{\_id}\`,\
> &#x20; \`GET /v1/exports/{\_id}\`, and \`GET /v1/tools/{\_id}\` — all fields are present.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowDescendantsResponse":{"type":"object","description":"The full resource objects for every import, export, and tool referenced by the flow. Useful for\nfetching a flow's entire dependency tree in a single call instead of resolving each resource\nindividually.","properties":{"imports":{"type":"array","description":"Import resources referenced by the flow's page processors.","items":{"type":"object","additionalProperties":true}},"exports":{"type":"array","description":"Export resources referenced by the flow's page generators and lookups.","items":{"type":"object","additionalProperties":true}},"tools":{"type":"array","description":"Tool resources referenced by the flow.","items":{"type":"object","additionalProperties":true}}},"required":["imports","exports","tools"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/descendants":{"get":{"operationId":"getFlowDescendants","tags":["Flows"],"summary":"Get a flow's descendant resources","description":"Returns the full resource objects for every import, export, and tool referenced by the flow.\nThis is a convenience endpoint that resolves the flow's entire dependency tree in a single\ncall — equivalent to reading the flow config and then fetching each referenced resource\nindividually, but without the N+1 round-trips.\n\nAI guidance:\n- Use this to inspect a flow's full wiring (connections, adaptors, mappings) without having to\n  walk `pageGenerators[].{_exportId}` and `pageProcessors[].{_importId}` manually.\n- The arrays mirror the resource shapes returned by `GET /v1/imports/{_id}`,\n  `GET /v1/exports/{_id}`, and `GET /v1/tools/{_id}` — all fields are present.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}}],"responses":{"200":{"description":"The flow's descendant resources.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowDescendantsResponse"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Summarize open errors across a flow's steps

> Returns a per-step count of currently open (unresolved) errors for the flow. Each entry carries the\
> step id and its open-error count; entries with zero errors still appear so the caller sees the full\
> step roster.\
> \
> AI guidance:\
> \- This is the flow-wide aggregate — for the full list of error records on a single step, call\
> &#x20; \`GET /v1/flows/{\_id}/{\_stepId}/errors\` (body-paginated).\
> \- For a whole-integration rollup, use \`GET /v1/integrations/{\_id}/errors\`.\
> \- \`lastErrorAt\` is only populated on entries with \`numError > 0\`.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowErrorsResponse":{"type":"object","description":"Per-step summary of open errors for a flow. One entry per export or import step; entries with\n`numError: 0` still appear so the caller can see the full step list.","properties":{"flowErrors":{"type":"array","description":"Per-step error counts.","items":{"type":"object","properties":{"_expOrImpId":{"type":"string","format":"objectId","description":"Id of the export or import step."},"numError":{"type":"integer","minimum":0,"description":"Count of currently open (unresolved) errors on this step."},"lastErrorAt":{"type":"string","format":"date-time","description":"Timestamp of the most recent open error on this step. Omitted when `numError` is 0."}},"required":["_expOrImpId","numError"]}}},"required":["flowErrors"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/errors":{"get":{"operationId":"listFlowErrors","tags":["Flows"],"summary":"Summarize open errors across a flow's steps","description":"Returns a per-step count of currently open (unresolved) errors for the flow. Each entry carries the\nstep id and its open-error count; entries with zero errors still appear so the caller sees the full\nstep roster.\n\nAI guidance:\n- This is the flow-wide aggregate — for the full list of error records on a single step, call\n  `GET /v1/flows/{_id}/{_stepId}/errors` (body-paginated).\n- For a whole-integration rollup, use `GET /v1/integrations/{_id}/errors`.\n- `lastErrorAt` is only populated on entries with `numError > 0`.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}}],"responses":{"200":{"description":"Per-step open-error summary.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowErrorsResponse"}}}},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Replace a connection across a flow

> Replaces every occurrence of one connection with another across all exports, imports, and lookups\
> in the flow. This is the recommended way to swap connections during environment promotion\
> (e.g. credential rotation) — it updates all references atomically\
> instead of requiring per-resource PUTs.\
> \
> The replacement connection must exist and be of the same adaptor type as the original. If the\
> types do not match, the request is rejected with a 422.\
> \
> AI guidance:\
> \- Prefer this over manually iterating descendants and patching \`\_connectionId\` on each one —\
> &#x20; this endpoint handles lookups and nested references that are easy to miss.\
> \- Pair with \`GET /v1/flows/{\_id}/descendants\` to verify which resources use a given connection\
> &#x20; before replacing it.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowReplaceConnectionRequest":{"type":"object","description":"Request body to replace one connection with another across all exports, imports, and lookups in a flow.\nBoth the current and replacement connection ids are required. The replacement connection must exist and\nbe of the same adaptor type as the original.","properties":{"_connectionId":{"type":"string","format":"objectId","description":"The id of the connection currently used by the flow's resources."},"_newConnectionId":{"type":"string","format":"objectId","description":"The id of the replacement connection to swap in."}},"required":["_connectionId","_newConnectionId"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422-unprocessable-entity":{"description":"Unprocessable entity. The request was well-formed but was unable to be followed due to semantic errors.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/replaceConnection":{"put":{"operationId":"replaceConnectionOnFlow","tags":["Flows"],"summary":"Replace a connection across a flow","description":"Replaces every occurrence of one connection with another across all exports, imports, and lookups\nin the flow. This is the recommended way to swap connections during environment promotion\n(e.g. credential rotation) — it updates all references atomically\ninstead of requiring per-resource PUTs.\n\nThe replacement connection must exist and be of the same adaptor type as the original. If the\ntypes do not match, the request is rejected with a 422.\n\nAI guidance:\n- Prefer this over manually iterating descendants and patching `_connectionId` on each one —\n  this endpoint handles lookups and nested references that are easy to miss.\n- Pair with `GET /v1/flows/{_id}/descendants` to verify which resources use a given connection\n  before replacing it.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowReplaceConnectionRequest"}}}},"responses":{"204":{"description":"Connection replaced successfully across all flow resources. No response body."},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"},"422":{"$ref":"#/components/responses/422-unprocessable-entity"}}}}}}
```

## Trigger a flow run

> Queues an on-demand run of the flow and returns the parent job id. The run is \*\*asynchronous\*\*: the\
> response returns as soon as the job is queued; use \`GET /v1/jobs/{\_id}\` (with the returned \`\_jobId\`)\
> or \`GET /v1/flows/{\_id}/jobs/latest\` to poll for terminal status.\
> \
> The request body is optional. When omitted, the flow runs with its configured schedule behavior —\
> for delta flows this means using the current \`lastExportDateTime\` as the lower bound. Pass\
> \`export.startDate\` / \`export.endDate\` to override the delta window for this run only (the flow's\
> checkpoint still advances on success). Pass \`\_exportIds\` to limit execution to a subset of the flow's\
> generators (useful for flows with many independent sources).\
> \
> Flow-level preconditions enforced by the platform:\
> \- The flow must not be \`disabled\`.\
> \- The flow must be in an enabled integration (when part of one).\
> \
> \
> AI guidance:\
> \- To trace a run end-to-end, arm debug (\`PUT /v1/flows/{\_id}\` with \`logging.debugUntil\` set to a\
> &#x20; future ISO timestamp) \*\*before\*\* calling this, then use the returned \`\_jobId\` with the execution-log\
> &#x20; endpoints.\
> \- For delta backfills, prefer passing explicit \`startDate\`/\`endDate\` over editing the export's\
> &#x20; \`lastExportDateTime\` — the override is scoped to one run and self-cleans.\
> \- A 200 with no body (or \`\_jobId\` absent) means the request was accepted but no job was queued —\
> &#x20; usually because another run is already in progress. Re-check \`GET /v1/jobs/current\` before retrying.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowRunRequest":{"type":"object","description":"Optional overrides for a manual flow run. Omit the body (or send `{}`) to run the flow with its default\nconfiguration.","properties":{"export":{"type":"object","description":"Delta-window override. When present, the run uses these dates in place of the flow's own\n`lastExportDateTime` / `currentExportDateTime`. Both fields are optional individually.","properties":{"startDate":{"type":"string","format":"date-time","description":"ISO-8601 start of the delta window (maps to `lastExportDateTime`)."},"endDate":{"type":"string","format":"date-time","description":"ISO-8601 end of the delta window (maps to `currentExportDateTime`)."}}},"_exportIds":{"type":"array","description":"Optional subset of exports (page generators) to run. Omit to run every generator on the flow.\nUseful for multi-generator flows where only one source needs re-pulling.","items":{"type":"string","format":"objectId"}}}},"FlowRunResponse":{"description":"Response from `POST /v1/flows/{_id}/run`. Shape varies by run type:\n\n- **Scheduled / queued run** — a single object with the new job's identifiers (e.g. `_id`, `_flowJobId`).\n- **On-demand / multi-export run** — an array of per-export run records.\n- **Rejected run** — an object with an `error` field (e.g. flow disabled, mutually-exclusive run already\n  in progress).\n\nCallers should branch on the response shape before treating it as a single job.","oneOf":[{"title":"Scheduled run","type":"object","additionalProperties":true,"description":"Single-job run result. Keys commonly include `_id`, `_flowJobId`, `status`."},{"type":"array","description":"Per-export run results for a multi-generator flow.","items":{"type":"object","additionalProperties":true}},{"title":"Run rejected","type":"object","description":"Run-rejected response.","properties":{"error":{"type":"string","description":"Human-readable reason the run was not started."}},"required":["error"]}]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422-unprocessable-entity":{"description":"Unprocessable entity. The request was well-formed but was unable to be followed due to semantic errors.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/run":{"post":{"operationId":"runFlow","tags":["Flows"],"summary":"Trigger a flow run","description":"Queues an on-demand run of the flow and returns the parent job id. The run is **asynchronous**: the\nresponse returns as soon as the job is queued; use `GET /v1/jobs/{_id}` (with the returned `_jobId`)\nor `GET /v1/flows/{_id}/jobs/latest` to poll for terminal status.\n\nThe request body is optional. When omitted, the flow runs with its configured schedule behavior —\nfor delta flows this means using the current `lastExportDateTime` as the lower bound. Pass\n`export.startDate` / `export.endDate` to override the delta window for this run only (the flow's\ncheckpoint still advances on success). Pass `_exportIds` to limit execution to a subset of the flow's\ngenerators (useful for flows with many independent sources).\n\nFlow-level preconditions enforced by the platform:\n- The flow must not be `disabled`.\n- The flow must be in an enabled integration (when part of one).\n\n\nAI guidance:\n- To trace a run end-to-end, arm debug (`PUT /v1/flows/{_id}` with `logging.debugUntil` set to a\n  future ISO timestamp) **before** calling this, then use the returned `_jobId` with the execution-log\n  endpoints.\n- For delta backfills, prefer passing explicit `startDate`/`endDate` over editing the export's\n  `lastExportDateTime` — the override is scoped to one run and self-cleans.\n- A 200 with no body (or `_jobId` absent) means the request was accepted but no job was queued —\n  usually because another run is already in progress. Re-check `GET /v1/jobs/current` before retrying.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowRunRequest"}}}},"responses":{"200":{"description":"Flow run accepted and queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowRunResponse"}}}},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"},"422":{"$ref":"#/components/responses/422-unprocessable-entity"}}}}}}
```

## Get a flow's trace-key patterns

> Returns the trace-key pattern for each page generator in the flow. Trace keys are used to\
> correlate source records with their downstream results in execution logs — they let you look up\
> "what happened to record X" without scanning the full log.\
> \
> Each entry in the returned array corresponds to one page generator (\`pgIndex\` matches the\
> zero-based position in the flow's \`pageGenerators\` array). The \`traceKeyPattern\` describes\
> which source-record fields and/or Handlebars templates are combined to produce the key.\
> \
> AI guidance:\
> \- Use this to understand how a flow identifies records for tracing before querying execution\
> &#x20; logs. If \`fields\` is empty and \`templates\` is empty, the flow has no trace key configured\
> &#x20; and log correlation must be done by position or other means.\
> \- Trace keys are especially important for flows that fan out one source record into many\
> &#x20; destination records — they are the primary way to reconnect results to their origin.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowTraceKeyResponse":{"type":"array","description":"One entry per page generator in the flow. Each entry describes the trace-key pattern used to\ncorrelate source records with their downstream results in execution logs.","items":{"type":"object","properties":{"pgIndex":{"type":"integer","description":"Zero-based index of the page generator in the flow's `pageGenerators` array."},"traceKeyPattern":{"type":"object","description":"The pattern used to derive trace keys for records produced by this generator.","properties":{"fields":{"type":"array","description":"Source-record field paths that contribute to the trace key.","items":{"type":"string"}},"templates":{"type":"array","description":"Handlebars templates that produce trace-key segments.","items":{"type":"string"}}}}}}},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/traceKey":{"get":{"operationId":"getFlowTraceKey","tags":["Flows"],"summary":"Get a flow's trace-key patterns","description":"Returns the trace-key pattern for each page generator in the flow. Trace keys are used to\ncorrelate source records with their downstream results in execution logs — they let you look up\n\"what happened to record X\" without scanning the full log.\n\nEach entry in the returned array corresponds to one page generator (`pgIndex` matches the\nzero-based position in the flow's `pageGenerators` array). The `traceKeyPattern` describes\nwhich source-record fields and/or Handlebars templates are combined to produce the key.\n\nAI guidance:\n- Use this to understand how a flow identifies records for tracing before querying execution\n  logs. If `fields` is empty and `templates` is empty, the flow has no trace key configured\n  and log correlation must be done by position or other means.\n- Trace keys are especially important for flows that fan out one source record into many\n  destination records — they are the primary way to reconnect results to their origin.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}}],"responses":{"200":{"description":"Trace-key patterns for each page generator in the flow.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowTraceKeyResponse"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Get the flow's delta checkpoint

> Returns the flow-level "last export date/time" checkpoint — the most recent export timestamp across all\
> generators (exports) in the flow. This value is what gets substituted into the \`{{lastExportDateTime}}\`\
> Handlebars variable on the next delta run of any export in the flow.\
> \
> The checkpoint advances automatically at the end of a successful delta run. It can be overridden per\
> run by passing \`export.startDate\` / \`export.endDate\` to \`POST /v1/flows/{\_id}/run\`.\
> \
> AI guidance:\
> \- Use this to answer "where is this flow's delta cursor?" without having to read the flow config or\
> &#x20; individual export records.\
> \- A missing or very old \`lastExportDateTime\` on a delta flow means the next run will re-scan the full\
> &#x20; history window from the source — expect a large job.\
> \- This is flow-scoped. Per-export checkpoints (for flows with multiple generators that advance\
> &#x20; independently) are exposed on the export record's \`delta\` block.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"LastExportDateTimeResponse":{"type":"object","description":"The flow's delta checkpoint — the most recent export timestamp across all page generators in the flow.\nUsed by delta-export logic to compute the next `{{lastExportDateTime}}` value.","properties":{"lastExportDateTime":{"type":["string","null"],"format":"date-time","description":"ISO-8601 timestamp. `null` if the flow has never produced an export."}},"required":["lastExportDateTime"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/lastExportDateTime":{"get":{"operationId":"getFlowLastExportDateTime","tags":["Flows"],"summary":"Get the flow's delta checkpoint","description":"Returns the flow-level \"last export date/time\" checkpoint — the most recent export timestamp across all\ngenerators (exports) in the flow. This value is what gets substituted into the `{{lastExportDateTime}}`\nHandlebars variable on the next delta run of any export in the flow.\n\nThe checkpoint advances automatically at the end of a successful delta run. It can be overridden per\nrun by passing `export.startDate` / `export.endDate` to `POST /v1/flows/{_id}/run`.\n\nAI guidance:\n- Use this to answer \"where is this flow's delta cursor?\" without having to read the flow config or\n  individual export records.\n- A missing or very old `lastExportDateTime` on a delta flow means the next run will re-scan the full\n  history window from the source — expect a large job.\n- This is flow-scoped. Per-export checkpoints (for flows with multiple generators that advance\n  independently) are exposed on the export record's `delta` block.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}}],"responses":{"200":{"description":"The flow's current delta checkpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LastExportDateTimeResponse"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Assign flows to a flow group

> Assigns one or more flows to a flow-grouping (section) within their integration. This is the\
> collection-level endpoint used by the UI's "move to section" action — it updates multiple flows in a\
> single call rather than requiring a per-flow \`PUT /v1/flows/{\_id}\` with a modified \`\_flowGroupingId\`.\
> \
> The flows referenced in \`\_flowIds\` must all belong to the same integration as the target\
> \`\_flowGroupingId\`. Pass \`\_flowGroupingId: null\` (or an empty string, depending on platform version)\
> to remove the flows from their current group back to the integration's default section.\
> \
> AI guidance:\
> \- Prefer this over N per-flow PUTs when moving a batch — it avoids the GET-modify-PUT round trip per\
> &#x20; flow and is atomic with respect to the UI's section view.\
> \- Flow groupings themselves are managed on the parent integration (\`PUT /v1/integrations/{\_id}\` with a\
> &#x20; modified \`flowGroupings\[]\` array). Create the group first, then call this to populate it.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"UpdateFlowGroupingRequest":{"type":"object","description":"Assign one or more flows to a flow group inside their parent integration. Replaces each flow's\ncurrent grouping membership; there is no multi-group membership model.","properties":{"_flowIds":{"type":"array","description":"The flows to move. All must belong to the same integration as the target flow group.","minItems":1,"items":{"type":"string","format":"objectId"}},"_flowGroupingId":{"type":["string","null"],"description":"Id of the flow group (within the integration's `flowGroupings[]`). Pass `null` (or an empty\nstring, depending on platform version) to remove the flows from their current group back to the\nintegration's default section."}},"required":["_flowIds","_flowGroupingId"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/updateFlowGrouping":{"put":{"operationId":"updateFlowGrouping","tags":["Flows"],"summary":"Assign flows to a flow group","description":"Assigns one or more flows to a flow-grouping (section) within their integration. This is the\ncollection-level endpoint used by the UI's \"move to section\" action — it updates multiple flows in a\nsingle call rather than requiring a per-flow `PUT /v1/flows/{_id}` with a modified `_flowGroupingId`.\n\nThe flows referenced in `_flowIds` must all belong to the same integration as the target\n`_flowGroupingId`. Pass `_flowGroupingId: null` (or an empty string, depending on platform version)\nto remove the flows from their current group back to the integration's default section.\n\nAI guidance:\n- Prefer this over N per-flow PUTs when moving a batch — it avoids the GET-modify-PUT round trip per\n  flow and is atomic with respect to the UI's section view.\n- Flow groupings themselves are managed on the parent integration (`PUT /v1/integrations/{_id}` with a\n  modified `flowGroupings[]` array). Create the group first, then call this to populate it.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateFlowGroupingRequest"}}}},"responses":{"204":{"description":"Flows reassigned. Empty response body (observed on success)."},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## List open errors on a flow step

> Returns one page of currently-open (unresolved) errors for a single step (export or import) within\
> a flow. The step id is the \`\_exportId\` / \`\_importId\` from the flow's \`pageGenerators\[]\`,\
> \`pageProcessors\[]\`, or \`routers\[].branches\[].pageProcessors\[]\`.\
> \
> Pagination is \*\*body-driven\*\*: follow the response's \`nextPageURL\` until it's \`null\`. The UI and CLI\
> walk this via \`listBodyPaginated\`; do not attempt \`Link\`-header pagination here.\
> \
> AI guidance:\
> \- For a flow-wide rollup (per-step counts only) use \`GET /v1/flows/{\_id}/errors\` instead — it's one\
> &#x20; call instead of N.\
> \- Filter client-side by \`\_flowJobId\` when you want errors from one specific run; the server-side\
> &#x20; query param is inconsistent and may under-return.\
> \- Errors with a \`retryDataKey\` are retryable via \`POST .../retry\`. Connection-level errors\
> &#x20; (\`classification: connection\`) typically lack one — rerun the whole flow to recover.\
> \- Pair with \`GET .../requests/{reqAndResKey}\` to pull the exact HTTP request/response the runtime\
> &#x20; captured at failure time.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowStepErrorsResponse":{"type":"object","description":"One page of open errors for a flow step. Body-paginated: when `nextPageURL` is present, follow it\nto fetch the next page.","properties":{"errors":{"type":"array","description":"Open error records on this page.","items":{"$ref":"#/components/schemas/FlowStepError"}},"nextPageURL":{"type":"string","description":"URL for the next page. **Omitted entirely** (not `null`) when there are no further pages.\nSome clients strip a leading `/api` prefix before reissuing."}},"required":["errors"]},"FlowStepError":{"type":"object","description":"One open-error record on a flow step. Errors accumulate per `(flow, step)` pair as the flow runs;\nthey remain \"open\" until a user marks them resolved (`PUT .../resolved`) or a successful retry\nauto-resolves them.","properties":{"errorId":{"type":"string","description":"Platform-assigned id for the error. This is the identifier you feed to assign / resolve /\ndelete-resolved endpoints via the `errorIds` (or `errors`) body array."},"occurredAt":{"type":"string","format":"date-time","description":"When the error happened (ISO 8601, UTC)."},"source":{"type":"string","description":"Where the error originated.\n- `application` — a target system returned a non-success HTTP status.\n- `connection` — low-level connection failure (timeout, TLS, DNS, etc.).\n- `internal` — the runtime itself failed processing the record.\n- `user` — validation or config error tripped before the call reached the target.\n- `pre_save_page_hook` — a preSavePage script threw or rejected."},"code":{"type":"string","description":"Error code. For HTTP-sourced errors this is the stringified HTTP status (`\"500\"`, `\"401\"`).\nFor platform-classified errors it's a symbolic code (e.g. `\"script_error\"`)."},"message":{"type":"string","description":"Human-readable message. Frequently a JSON string that the adaptor received as a response body."},"oIndex":{"type":"string","description":"Zero-based index of the offending record within its batch (page). Paired with `_flowJobId` this\npinpoints the record inside the run's execution log."},"_flowJobId":{"type":"string","format":"objectId","description":"Id of the flow-run job this error came from. Use with `GET /v1/jobs/{_id}` for run context."},"traceKey":{"type":"string","description":"Upstream export/record identifier that produced this error — correlates the error back to the\nsource record across the execution log. Populated on every error in practice; callers doing\nrecord-level triage join on this field."},"classification":{"type":"string","description":"Category assigned by the platform (or a user) to this error — drives auto-retry and reporting.\nObserved values include:\n- `connection` — low-level connection failure.\n- `intermittent` — transient target-side failure (4xx / 5xx that the platform will auto-retry\n  at the `retryAt` timestamp).\n- `validation` — request failed pre-submit validation.\n- `data` — record-level data failure (malformed, missing fields).\n- `system` — internal runtime error.\nEmpty when unclassified."},"classifiedBy":{"type":"string","description":"`auto` when the platform classified it, or a user id / email when a human did."},"reqAndResKey":{"type":"string","description":"Opaque key for the stored HTTP request+response pair associated with this error. Pass to\n`GET /v1/flows/{_id}/{_stepId}/requests/{reqAndResKey}` to fetch the decoded HTTP detail. Absent\nwhen the error was not produced by an HTTP adaptor."},"retryDataKey":{"type":"string","description":"Opaque key for the per-record data snapshot captured at the moment of failure. Populated on\nrecord-level errors (imports, transforms) where a retry means re-running the record; absent on\nconnection-level failures. Pass to `POST /v1/flows/{_id}/{_stepId}/retry` (as `retryDataKeys[]`)\nto retry, or to `GET /v1/flows/{_id}/{_stepId}/{retryDataKey}/data` to inspect / mutate the\nsnapshot before retry."},"purgeAt":{"type":"string","description":"Epoch-milliseconds timestamp (as a string) when the error record is scheduled for automatic\ndeletion from the queue. Drives the 30-day retention window by default."},"retryAt":{"type":"string","format":"date-time","description":"When the platform is scheduled to auto-retry this error. Populated on `classification:\nintermittent` errors (the platform retries with exponential backoff up to a cap). Absent on\nerrors that won't be auto-retried."},"tags":{"type":["array","null"],"description":"Tag names currently attached to this error, or `null` when no tags are set. Stored as the\nhuman-readable `tag` value (e.g. `\"Investigating\"`), **not** the short `tagId` code used when\nwriting via `PUT /v1/flows/{_id}/{_stepId}/tags`. Resolve names ↔ codes via `GET /v1/tags`.","items":{"type":"string"}},"assignedTo":{"type":"string","description":"Display name of the user currently assigned to this error for triage when the email resolves\nto a known account user (e.g. `\"Tyler Lamparter\"`). When the email does not match a known\nuser, the literal email string is stored instead. Set via\n`PUT /v1/flows/{_id}/{_stepId}/errors/assign`. Absent when no assignment has been made."},"assignedBy":{"type":"string","description":"Mongo user id of the user who made the assignment. Absent when no assignment has been made."},"_assignedToUserId":{"type":"string","format":"objectId","description":"Mongo user id of the assignee. Paired with `assignedTo` for callers that need the id directly."}},"required":["errorId","occurredAt","source","code","message"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/{_stepId}/errors":{"get":{"operationId":"listFlowStepErrors","tags":["Flows"],"summary":"List open errors on a flow step","description":"Returns one page of currently-open (unresolved) errors for a single step (export or import) within\na flow. The step id is the `_exportId` / `_importId` from the flow's `pageGenerators[]`,\n`pageProcessors[]`, or `routers[].branches[].pageProcessors[]`.\n\nPagination is **body-driven**: follow the response's `nextPageURL` until it's `null`. The UI and CLI\nwalk this via `listBodyPaginated`; do not attempt `Link`-header pagination here.\n\nAI guidance:\n- For a flow-wide rollup (per-step counts only) use `GET /v1/flows/{_id}/errors` instead — it's one\n  call instead of N.\n- Filter client-side by `_flowJobId` when you want errors from one specific run; the server-side\n  query param is inconsistent and may under-return.\n- Errors with a `retryDataKey` are retryable via `POST .../retry`. Connection-level errors\n  (`classification: connection`) typically lack one — rerun the whole flow to recover.\n- Pair with `GET .../requests/{reqAndResKey}` to pull the exact HTTP request/response the runtime\n  captured at failure time.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_stepId","in":"path","required":true,"description":"Export or import id — the step within the flow.","schema":{"type":"string","format":"objectId"}}],"responses":{"200":{"description":"One page of open errors on this step.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepErrorsResponse"}}}},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Assign open errors to a user

> Tags a batch of open errors with an assignee for triage workflows. The errors stay open — this does\
> not resolve or retry them — they simply appear in the assignee's "my errors" view until another\
> action moves them.\
> \
> AI guidance:\
> \- \`email\` values are accepted verbatim — the API does NOT validate them against the account's\
> &#x20; user list. Passing a string that doesn't match an existing user still returns 200 and persists\
> &#x20; the arbitrary string as \`assignedTo\` (with a synthetic \`\_assignedToUserId\`). Callers that need\
> &#x20; validation should check against \`GET /v1/ashares\` client-side before assigning.\
> \- Chunk large batches (\~1000 ids) across multiple calls; the CLI's built-in batcher uses 1000.\
> \- No body shape exists to \*un\*assign — assigning the same batch to a different user simply overwrites\
> &#x20; the prior assignment.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowStepErrorsAssignRequest":{"type":"object","description":"Request body for `PUT /v1/flows/{_id}/{_stepId}/errors/assign`. Assigns a batch of open errors to a\nuser by email; the errors remain open but are tagged with the assignee for triage views.","properties":{"errorIds":{"type":"array","description":"Ids of open errors to assign. Obtain from `GET /v1/flows/{_id}/{_stepId}/errors` → each entry's\n`errorId`. Platform caps batch size around ~1000; chunk larger sets client-side.","minItems":1,"items":{"type":"string"}},"email":{"type":"string","format":"email","description":"Email of the account user to assign the errors to. Must be a user who has access to the account;\nthe API does not create users implicitly."}},"required":["errorIds","email"]},"FlowStepAffectedErrorsResponse":{"type":"object","description":"Echo of which error records the mutation touched. Returned by `PUT .../errors/assign`.","properties":{"errorsToReturn":{"type":"array","description":"Error ids that were affected by the mutation.","items":{"type":"string"}}},"required":["errorsToReturn"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/{_stepId}/errors/assign":{"put":{"operationId":"assignFlowStepErrors","tags":["Flows"],"summary":"Assign open errors to a user","description":"Tags a batch of open errors with an assignee for triage workflows. The errors stay open — this does\nnot resolve or retry them — they simply appear in the assignee's \"my errors\" view until another\naction moves them.\n\nAI guidance:\n- `email` values are accepted verbatim — the API does NOT validate them against the account's\n  user list. Passing a string that doesn't match an existing user still returns 200 and persists\n  the arbitrary string as `assignedTo` (with a synthetic `_assignedToUserId`). Callers that need\n  validation should check against `GET /v1/ashares` client-side before assigning.\n- Chunk large batches (~1000 ids) across multiple calls; the CLI's built-in batcher uses 1000.\n- No body shape exists to *un*assign — assigning the same batch to a different user simply overwrites\n  the prior assignment.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_stepId","in":"path","required":true,"description":"Export or import id.","schema":{"type":"string","format":"objectId"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepErrorsAssignRequest"}}}},"responses":{"200":{"description":"Errors assigned. Body echoes which ids were affected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepAffectedErrorsResponse"}}}},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Remove assignment from open errors

> Removes the assignee from a batch of open errors. The errors remain open — this is the inverse\
> of \`PUT .../errors/assign\`. Non-existent error ids are silently ignored (no error raised).\
> \
> AI guidance:\
> \- Use this to clear triage assignments when errors are being re-triaged or the assigned user\
> &#x20; is no longer responsible.\
> \- The response's \`errorsToReturn\` contains only ids that were actually unassigned — if an id\
> &#x20; was already unassigned or doesn't exist, it's omitted from the response.\
> \- Pair with \`GET .../errors\` filtered client-side by \`assignedTo\` to find all errors currently\
> &#x20; assigned to a specific user before bulk-unassigning.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowStepErrorsUnassignRequest":{"type":"object","description":"Request body for `PUT /v1/flows/{_id}/{_stepId}/errors/unassign`. Removes the assignee from a\nbatch of open errors. Non-existent error ids are silently ignored.","properties":{"errorIds":{"type":"array","description":"Ids of open errors to unassign. Obtain from `GET /v1/flows/{_id}/{_stepId}/errors` → each\nentry's `errorId`. Non-existent ids are silently ignored (no error raised).","minItems":1,"items":{"type":"string"}}},"required":["errorIds"]},"FlowStepErrorsUnassignResponse":{"type":"object","description":"Response from `PUT /v1/flows/{_id}/{_stepId}/errors/unassign`. Echoes which error ids were\nactually unassigned — ids that were not found or were already unassigned are omitted.","properties":{"errorsToReturn":{"type":"array","description":"Error ids that were actually unassigned by this call.","items":{"type":"string"}}},"required":["errorsToReturn"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/{_stepId}/errors/unassign":{"put":{"operationId":"unassignFlowStepErrors","tags":["Flows"],"summary":"Remove assignment from open errors","description":"Removes the assignee from a batch of open errors. The errors remain open — this is the inverse\nof `PUT .../errors/assign`. Non-existent error ids are silently ignored (no error raised).\n\nAI guidance:\n- Use this to clear triage assignments when errors are being re-triaged or the assigned user\n  is no longer responsible.\n- The response's `errorsToReturn` contains only ids that were actually unassigned — if an id\n  was already unassigned or doesn't exist, it's omitted from the response.\n- Pair with `GET .../errors` filtered client-side by `assignedTo` to find all errors currently\n  assigned to a specific user before bulk-unassigning.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_stepId","in":"path","required":true,"description":"Export or import id.","schema":{"type":"string","format":"objectId"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepErrorsUnassignRequest"}}}},"responses":{"200":{"description":"Errors unassigned. Body echoes which ids were actually affected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepErrorsUnassignResponse"}}}},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Get a signed URL to download open errors as CSV

> Returns a pre-signed S3 URL that streams all currently-open errors for a flow step as a CSV\
> file. The URL expires after approximately 15 minutes. The CSV always includes a header row,\
> even when the step has zero open errors.\
> \
> CSV columns: \`occurredAt\`, \`source\`, \`code\`, \`message\`, \`traceKey\`, \`exportDataURI\`,\
> \`importDataURI\`, \`oIndex\`, \`retryDataKey\`, \`errorId\`, \`legacyId\`, \`reqAndResKey\`, \`purgeAt\`,\
> \`tags\`, \`assignedTo\`, \`assignedBy\`, \`\_assignedToUserId\`.\
> \
> AI guidance:\
> \- Use this when you need all open errors in a single download rather than paginating through\
> &#x20; \`GET .../errors\`. The CSV is generated on-demand and reflects the current error state.\
> \- The \`startAtErrorId\` query param lets you resume a partial download — pass the last \`errorId\`\
> &#x20; from a previous CSV to skip already-seen records.\
> \- The signed URL requires no auth headers — it's a plain S3 GET. Do not attach your bearer\
> &#x20; token when fetching the CSV.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowStepSignedURLResponse":{"type":"object","description":"Pre-signed S3 URL for downloading error or retry data as a CSV file. The URL expires after\napproximately 15 minutes. Returned by the `signedURL` endpoints on errors, resolved errors,\nand retry data.","properties":{"signedURL":{"type":"string","format":"uri","description":"Pre-signed S3 URL that streams a CSV file when fetched with a plain GET (no auth headers\nneeded). Expires ~15 minutes after generation. The CSV always includes a header row, even\nwhen there are zero matching records."}},"required":["signedURL"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/{_stepId}/errors/signedURL":{"get":{"operationId":"getFlowStepErrorsSignedURL","tags":["Flows"],"summary":"Get a signed URL to download open errors as CSV","description":"Returns a pre-signed S3 URL that streams all currently-open errors for a flow step as a CSV\nfile. The URL expires after approximately 15 minutes. The CSV always includes a header row,\neven when the step has zero open errors.\n\nCSV columns: `occurredAt`, `source`, `code`, `message`, `traceKey`, `exportDataURI`,\n`importDataURI`, `oIndex`, `retryDataKey`, `errorId`, `legacyId`, `reqAndResKey`, `purgeAt`,\n`tags`, `assignedTo`, `assignedBy`, `_assignedToUserId`.\n\nAI guidance:\n- Use this when you need all open errors in a single download rather than paginating through\n  `GET .../errors`. The CSV is generated on-demand and reflects the current error state.\n- The `startAtErrorId` query param lets you resume a partial download — pass the last `errorId`\n  from a previous CSV to skip already-seen records.\n- The signed URL requires no auth headers — it's a plain S3 GET. Do not attach your bearer\n  token when fetching the CSV.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_stepId","in":"path","required":true,"description":"Export or import id — the step within the flow.","schema":{"type":"string","format":"objectId"}},{"name":"startAtErrorId","in":"query","required":false,"description":"Resume from this error id — errors with ids lexically before this value are excluded from\nthe CSV. Useful for incremental downloads.","schema":{"type":"string"}}],"responses":{"200":{"description":"Pre-signed S3 URL for the errors CSV.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepSignedURLResponse"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## List resolved errors on a flow step

> Returns one page of already-resolved errors for a flow step. Body-paginated via \`nextPageURL\` (same\
> shape as the open-errors listing).\
> \
> Errors arrive here either because a user marked them resolved (\`PUT .../resolved\`) or because a\
> successful retry auto-resolved them. The platform retains resolved errors through the account's\
> retention window; use \`DELETE .../resolved\` to purge them earlier.\
> \
> AI guidance:\
> \- Use this to build audit / "what did we close this week" views. For live open-error queues, use\
> &#x20; \`GET .../errors\` instead.\
> \- \`resolvedBy: auto\` means a retry cleared the error; a Mongo user id means a human clicked\
> &#x20; resolve. This is the field to distinguish manual triage from auto-recovery.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowStepResolvedResponse":{"type":"object","description":"One page of resolved errors for a flow step. Resolved errors are retained for audit (and for\npotential un-resolving, though that's not exposed as an API operation) until either a user deletes\nthem via `DELETE .../resolved` or the purge window expires.","properties":{"resolved":{"type":"array","description":"Resolved error records on this page.","items":{"allOf":[{"$ref":"#/components/schemas/FlowStepError"},{"type":"object","description":"Fields added when an error transitions from open to resolved.","properties":{"resolvedAt":{"type":"string","format":"date-time","description":"When the error was marked resolved."},"resolvedBy":{"type":"string","description":"`\"auto\"` when the platform auto-resolved (typically because a retry cleared the error\nor a connection-class error was auto-resolved at the end of a job), or a Mongo **user\nid** (not email) when a human marked it resolved via `PUT .../resolved`.\nCross-reference via `GET /v1/ashares/{_id}` to resolve the id to a profile."}}}]}},"nextPageURL":{"type":"string","description":"URL for the next page. **Omitted entirely** (not `null`) when there are no further pages."}},"required":["resolved"]},"FlowStepError":{"type":"object","description":"One open-error record on a flow step. Errors accumulate per `(flow, step)` pair as the flow runs;\nthey remain \"open\" until a user marks them resolved (`PUT .../resolved`) or a successful retry\nauto-resolves them.","properties":{"errorId":{"type":"string","description":"Platform-assigned id for the error. This is the identifier you feed to assign / resolve /\ndelete-resolved endpoints via the `errorIds` (or `errors`) body array."},"occurredAt":{"type":"string","format":"date-time","description":"When the error happened (ISO 8601, UTC)."},"source":{"type":"string","description":"Where the error originated.\n- `application` — a target system returned a non-success HTTP status.\n- `connection` — low-level connection failure (timeout, TLS, DNS, etc.).\n- `internal` — the runtime itself failed processing the record.\n- `user` — validation or config error tripped before the call reached the target.\n- `pre_save_page_hook` — a preSavePage script threw or rejected."},"code":{"type":"string","description":"Error code. For HTTP-sourced errors this is the stringified HTTP status (`\"500\"`, `\"401\"`).\nFor platform-classified errors it's a symbolic code (e.g. `\"script_error\"`)."},"message":{"type":"string","description":"Human-readable message. Frequently a JSON string that the adaptor received as a response body."},"oIndex":{"type":"string","description":"Zero-based index of the offending record within its batch (page). Paired with `_flowJobId` this\npinpoints the record inside the run's execution log."},"_flowJobId":{"type":"string","format":"objectId","description":"Id of the flow-run job this error came from. Use with `GET /v1/jobs/{_id}` for run context."},"traceKey":{"type":"string","description":"Upstream export/record identifier that produced this error — correlates the error back to the\nsource record across the execution log. Populated on every error in practice; callers doing\nrecord-level triage join on this field."},"classification":{"type":"string","description":"Category assigned by the platform (or a user) to this error — drives auto-retry and reporting.\nObserved values include:\n- `connection` — low-level connection failure.\n- `intermittent` — transient target-side failure (4xx / 5xx that the platform will auto-retry\n  at the `retryAt` timestamp).\n- `validation` — request failed pre-submit validation.\n- `data` — record-level data failure (malformed, missing fields).\n- `system` — internal runtime error.\nEmpty when unclassified."},"classifiedBy":{"type":"string","description":"`auto` when the platform classified it, or a user id / email when a human did."},"reqAndResKey":{"type":"string","description":"Opaque key for the stored HTTP request+response pair associated with this error. Pass to\n`GET /v1/flows/{_id}/{_stepId}/requests/{reqAndResKey}` to fetch the decoded HTTP detail. Absent\nwhen the error was not produced by an HTTP adaptor."},"retryDataKey":{"type":"string","description":"Opaque key for the per-record data snapshot captured at the moment of failure. Populated on\nrecord-level errors (imports, transforms) where a retry means re-running the record; absent on\nconnection-level failures. Pass to `POST /v1/flows/{_id}/{_stepId}/retry` (as `retryDataKeys[]`)\nto retry, or to `GET /v1/flows/{_id}/{_stepId}/{retryDataKey}/data` to inspect / mutate the\nsnapshot before retry."},"purgeAt":{"type":"string","description":"Epoch-milliseconds timestamp (as a string) when the error record is scheduled for automatic\ndeletion from the queue. Drives the 30-day retention window by default."},"retryAt":{"type":"string","format":"date-time","description":"When the platform is scheduled to auto-retry this error. Populated on `classification:\nintermittent` errors (the platform retries with exponential backoff up to a cap). Absent on\nerrors that won't be auto-retried."},"tags":{"type":["array","null"],"description":"Tag names currently attached to this error, or `null` when no tags are set. Stored as the\nhuman-readable `tag` value (e.g. `\"Investigating\"`), **not** the short `tagId` code used when\nwriting via `PUT /v1/flows/{_id}/{_stepId}/tags`. Resolve names ↔ codes via `GET /v1/tags`.","items":{"type":"string"}},"assignedTo":{"type":"string","description":"Display name of the user currently assigned to this error for triage when the email resolves\nto a known account user (e.g. `\"Tyler Lamparter\"`). When the email does not match a known\nuser, the literal email string is stored instead. Set via\n`PUT /v1/flows/{_id}/{_stepId}/errors/assign`. Absent when no assignment has been made."},"assignedBy":{"type":"string","description":"Mongo user id of the user who made the assignment. Absent when no assignment has been made."},"_assignedToUserId":{"type":"string","format":"objectId","description":"Mongo user id of the assignee. Paired with `assignedTo` for callers that need the id directly."}},"required":["errorId","occurredAt","source","code","message"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/{_stepId}/resolved":{"get":{"operationId":"listFlowStepResolvedErrors","tags":["Flows"],"summary":"List resolved errors on a flow step","description":"Returns one page of already-resolved errors for a flow step. Body-paginated via `nextPageURL` (same\nshape as the open-errors listing).\n\nErrors arrive here either because a user marked them resolved (`PUT .../resolved`) or because a\nsuccessful retry auto-resolved them. The platform retains resolved errors through the account's\nretention window; use `DELETE .../resolved` to purge them earlier.\n\nAI guidance:\n- Use this to build audit / \"what did we close this week\" views. For live open-error queues, use\n  `GET .../errors` instead.\n- `resolvedBy: auto` means a retry cleared the error; a Mongo user id means a human clicked\n  resolve. This is the field to distinguish manual triage from auto-recovery.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_stepId","in":"path","required":true,"description":"Export or import id.","schema":{"type":"string","format":"objectId"}}],"responses":{"200":{"description":"One page of resolved errors.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepResolvedResponse"}}}},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Mark open errors as resolved

> Moves a batch of currently-open errors to the resolved list. The underlying records are unchanged —\
> no retry happens; this is purely an administrative state change used to clear the open-errors queue\
> after a user has reviewed the failures and decided they're not actionable.\
> \
> AI guidance:\
> \- To actually re-run the failed records, use \`POST .../retry\` with their \`retryDataKeys\` — that will\
> &#x20; auto-resolve the underlying errors on success.\
> \- The request body field is named \`errors\` (carrying error ids), not \`errorIds\` — legacy shape.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowStepResolveRequest":{"type":"object","description":"Request body for `PUT /v1/flows/{_id}/{_stepId}/resolved`. Marks a batch of currently-open errors\nas resolved — they move from the `errors` list to the `resolved` list. The body field is named\n`errors` (not `errorIds`) for historical reasons; it carries error ids.","properties":{"errors":{"type":"array","description":"Ids of open errors to mark resolved. Obtain from `GET /v1/flows/{_id}/{_stepId}/errors` → each\nentry's `errorId`.","minItems":1,"items":{"type":"string"}}},"required":["errors"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/{_stepId}/resolved":{"put":{"operationId":"resolveFlowStepErrors","tags":["Flows"],"summary":"Mark open errors as resolved","description":"Moves a batch of currently-open errors to the resolved list. The underlying records are unchanged —\nno retry happens; this is purely an administrative state change used to clear the open-errors queue\nafter a user has reviewed the failures and decided they're not actionable.\n\nAI guidance:\n- To actually re-run the failed records, use `POST .../retry` with their `retryDataKeys` — that will\n  auto-resolve the underlying errors on success.\n- The request body field is named `errors` (carrying error ids), not `errorIds` — legacy shape.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_stepId","in":"path","required":true,"description":"Export or import id.","schema":{"type":"string","format":"objectId"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepResolveRequest"}}}},"responses":{"204":{"description":"Errors resolved (no body)."},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Permanently delete resolved errors

> Permanently removes resolved error records from the account. Use when the retention window hasn't\
> expired yet but you want to clear out the resolved list (e.g. after a one-time cleanup pass).\
> \
> AI guidance:\
> \- Only resolved errors can be deleted through this endpoint. Open errors must be resolved first.\
> \- This is destructive — the records are gone, not archived. The audit trail on the parent job remains\
> &#x20; intact, but the per-record HTTP request/response captures associated with each error are also\
> &#x20; removed.\
> \- Body field is \`errors\` (legacy shape) carrying error ids.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowStepResolvedDeleteRequest":{"type":"object","description":"Request body for `DELETE /v1/flows/{_id}/{_stepId}/resolved`. Permanently deletes the named\nresolved errors from the account. The body field is named `errors` (carries error ids) — this\nmatches the shape used by the resolve PUT.","properties":{"errors":{"type":"array","description":"Ids of resolved errors to delete. Obtain from `GET /v1/flows/{_id}/{_stepId}/resolved` → each\nentry's `errorId`.","minItems":1,"items":{"type":"string"}}},"required":["errors"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/{_stepId}/resolved":{"delete":{"operationId":"deleteFlowStepResolvedErrors","tags":["Flows"],"summary":"Permanently delete resolved errors","description":"Permanently removes resolved error records from the account. Use when the retention window hasn't\nexpired yet but you want to clear out the resolved list (e.g. after a one-time cleanup pass).\n\nAI guidance:\n- Only resolved errors can be deleted through this endpoint. Open errors must be resolved first.\n- This is destructive — the records are gone, not archived. The audit trail on the parent job remains\n  intact, but the per-record HTTP request/response captures associated with each error are also\n  removed.\n- Body field is `errors` (legacy shape) carrying error ids.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_stepId","in":"path","required":true,"description":"Export or import id.","schema":{"type":"string","format":"objectId"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepResolvedDeleteRequest"}}}},"responses":{"204":{"description":"Resolved errors deleted (no body)."},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Get a signed URL to download resolved errors as CSV

> Returns a pre-signed S3 URL that streams all resolved errors for a flow step as a CSV file.\
> The URL expires after approximately 15 minutes. The CSV always includes a header row, even\
> when there are zero resolved errors.\
> \
> The CSV includes the same columns as the open-errors signed URL, plus two prepended columns:\
> \`resolvedAt\` and \`resolvedBy\`.\
> \
> Full CSV columns: \`resolvedAt\`, \`resolvedBy\`, \`occurredAt\`, \`source\`, \`code\`, \`message\`,\
> \`traceKey\`, \`exportDataURI\`, \`importDataURI\`, \`oIndex\`, \`retryDataKey\`, \`errorId\`, \`legacyId\`,\
> \`reqAndResKey\`, \`purgeAt\`, \`tags\`, \`assignedTo\`, \`assignedBy\`, \`\_assignedToUserId\`.\
> \
> AI guidance:\
> \- Use this for audit/compliance exports of resolved errors. For currently-open errors, use\
> &#x20; \`GET .../errors/signedURL\` instead.\
> \- \`resolvedBy\` is either a user id (manual resolve) or \`"auto"\` (resolved by a successful\
> &#x20; retry).

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowStepSignedURLResponse":{"type":"object","description":"Pre-signed S3 URL for downloading error or retry data as a CSV file. The URL expires after\napproximately 15 minutes. Returned by the `signedURL` endpoints on errors, resolved errors,\nand retry data.","properties":{"signedURL":{"type":"string","format":"uri","description":"Pre-signed S3 URL that streams a CSV file when fetched with a plain GET (no auth headers\nneeded). Expires ~15 minutes after generation. The CSV always includes a header row, even\nwhen there are zero matching records."}},"required":["signedURL"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/{_stepId}/resolved/signedURL":{"get":{"operationId":"getFlowStepResolvedSignedURL","tags":["Flows"],"summary":"Get a signed URL to download resolved errors as CSV","description":"Returns a pre-signed S3 URL that streams all resolved errors for a flow step as a CSV file.\nThe URL expires after approximately 15 minutes. The CSV always includes a header row, even\nwhen there are zero resolved errors.\n\nThe CSV includes the same columns as the open-errors signed URL, plus two prepended columns:\n`resolvedAt` and `resolvedBy`.\n\nFull CSV columns: `resolvedAt`, `resolvedBy`, `occurredAt`, `source`, `code`, `message`,\n`traceKey`, `exportDataURI`, `importDataURI`, `oIndex`, `retryDataKey`, `errorId`, `legacyId`,\n`reqAndResKey`, `purgeAt`, `tags`, `assignedTo`, `assignedBy`, `_assignedToUserId`.\n\nAI guidance:\n- Use this for audit/compliance exports of resolved errors. For currently-open errors, use\n  `GET .../errors/signedURL` instead.\n- `resolvedBy` is either a user id (manual resolve) or `\"auto\"` (resolved by a successful\n  retry).","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_stepId","in":"path","required":true,"description":"Export or import id.","schema":{"type":"string","format":"objectId"}},{"name":"startAtErrorId","in":"query","required":false,"description":"Resume from this error id — errors with ids lexically before this value are excluded from\nthe CSV.","schema":{"type":"string"}}],"responses":{"200":{"description":"Pre-signed S3 URL for the resolved errors CSV.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepSignedURLResponse"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Retry errored records

> Re-runs the per-record data snapshots captured when the listed errors occurred. A successful retry\
> auto-resolves the underlying open-error record. A retry that fails again stays open (and may\
> accumulate error history, depending on the adaptor).\
> \
> Only errors that carry a \`retryDataKey\` can be retried — typically these are record-level errors\
> from imports or transforms. Connection-level errors (\`classification: connection\`) don't have a\
> \`retryDataKey\`; to recover from those, re-run the whole flow after fixing the connection.\
> \
> \*\*Response behavior splits on whether any key matched:\*\*\
> \- At least one valid \`retryDataKey\` → \*\*200\*\* with a \`type: "retry"\` Job record (the queued retry\
> &#x20; job; poll it via \`GET /v1/jobs/{\_id}\`). A successful retry clears the original error from\
> &#x20; \`GET .../errors\` and moves it into \`/resolved\` with \`resolvedBy\` set to the user who triggered\
> &#x20; the retry (not \`"auto"\`, despite what older docs say).\
> \- No keys matched any stored snapshot → \*\*204\*\* silent no-op. There is no per-key validation: the\
> &#x20; endpoint does not 400 on bogus keys; callers must poll \`GET .../errors\` to confirm any change.\
> \
> \*\*Retry outcome semantics.\*\* A retry that still fails generates a \*\*new\*\* error record with a new\
> \`errorId\` (the original one is auto-resolved when the retry ultimately succeeds, or stays open\
> pending next retry). Building a UI on top of this endpoint needs to reconcile the "before" and\
> "after" error lists by \`retryDataKey\`, not \`errorId\`.\
> \
> AI guidance:\
> \- To modify the record before retrying (e.g. fix a bad field), call\
> &#x20; \`GET /v1/flows/{\_id}/{\_stepId}/{retryDataKey}/data\`, mutate the payload, \`PUT\` it back, \*\*then\*\*\
> &#x20; call this endpoint.\
> \- Retrying a batch does not guarantee ordering relative to fresh incoming data; the retried records\
> &#x20; go through the same page-processor pipeline as new records.\
> \- The CLI batches at 1000 per call; match that cap when building large retry sets.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowStepRetryRequest":{"type":"object","description":"Request body for `POST /v1/flows/{_id}/{_stepId}/retry`. Re-runs the per-record data snapshot\ncaptured at the moment each error occurred. A successful retry auto-resolves the underlying error.","properties":{"retryDataKeys":{"type":"array","description":"Opaque per-error snapshot keys. Obtain from `GET /v1/flows/{_id}/{_stepId}/errors` →\n`retryDataKey` on each entry that has one. Errors without a `retryDataKey` (typically\nconnection-level failures) cannot be retried via this endpoint — rerun the whole flow instead.","minItems":1,"items":{"type":"string"}}},"required":["retryDataKeys"]},"Job":{"type":"object","description":"A job represents one execution of a flow/export/import (or a retry) in integrator.io.\nJobs are primarily read-only records created by the platform when executions occur.\n","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Job id."},"_userId":{"type":"string","format":"objectId","readOnly":true,"description":"Owner user id for the job."},"type":{"type":"string","readOnly":true,"description":"Job type.\n- `flow`: a flow run (parent job)\n- `export` / `import`: child jobs for an export/import step\n- `retry` / `bulk_retry`: error management retries\n","enum":["export","import","flow","retry","bulk_retry"]},"status":{"type":"string","readOnly":true,"description":"Current job status.","enum":["queued","running","retrying","completed","failed","canceled","canceling"]},"_integrationId":{"type":"string","format":"objectId","readOnly":true,"description":"Integration id this job belongs to (if applicable)."},"_flowId":{"type":"string","format":"objectId","readOnly":true,"description":"Flow id this job belongs to (if applicable)."},"_exportId":{"type":"string","format":"objectId","readOnly":true,"description":"Export id. Present on child export jobs and also on parent flow\njobs (where it references the first page-generator export)."},"_importId":{"type":"string","format":"objectId","readOnly":true,"description":"Import id for import child jobs (if applicable)."},"_expOrImpId":{"type":"string","format":"objectId","readOnly":true,"description":"Internal reference to an export/import for branched flows (if applicable)."},"_retryOfJobId":{"type":"string","format":"objectId","readOnly":true,"description":"If this is a retry job, the original job id being retried."},"_flowJobId":{"type":"string","format":"objectId","readOnly":true,"description":"Parent flow job id (for child jobs)."},"_parentJobId":{"type":"string","format":"objectId","readOnly":true,"description":"Parent job id (used for branched flows / hierarchy)."},"_bulkJobId":{"type":"string","format":"objectId","readOnly":true,"description":"Bulk retry parent job id (if applicable)."},"startedAt":{"type":"string","format":"date-time","readOnly":true,"description":"When execution started."},"endedAt":{"type":"string","format":"date-time","readOnly":true,"description":"When execution ended."},"resolvedAt":{"type":"string","format":"date-time","readOnly":true,"description":"When errors for the job were fully resolved (if applicable)."},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"When the job record was created."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Last modification time for the job record."},"lastExecutedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Last time the job executed work (may differ from createdAt/startedAt)."},"purgeAt":{"type":"string","format":"date-time","readOnly":true,"description":"When the job should be purged from primary storage."},"clickhousePurgeAt":{"type":"string","format":"date-time","readOnly":true,"description":"When the job should be purged from ClickHouse (if enabled)."},"triggeredBy":{"type":"string","readOnly":true,"description":"Who/what triggered the job (free-form string)."},"canceledBy":{"type":"string","readOnly":true,"description":"Who/what requested cancellation (free-form string)."},"flowExecutionGroupId":{"type":"string","readOnly":true,"description":"Groups multiple related jobs for a single flow execution."},"numError":{"type":"integer","readOnly":true,"description":"Total number of errors produced by the job (including resolved ones).\nUse `numOpenError` for the count of currently unresolved errors.\n"},"numOpenError":{"type":"integer","readOnly":true,"description":"Number of unresolved errors (equivalent to `numError - numResolved`).\nThis is the value dashboards surface as \"errors needing attention.\"\n"},"numResolved":{"type":"integer","readOnly":true,"description":"Number of resolved errors."},"numResolvedByAdaptor":{"type":"integer","readOnly":true,"description":"Number of errors resolved by the adaptor."},"numSuccess":{"type":"integer","readOnly":true,"description":"Number of successful records/pages."},"numIgnore":{"type":"integer","readOnly":true,"description":"Number of ignored records/pages."},"numExport":{"type":"integer","readOnly":true,"description":"Legacy field used by retry logic. May be deprecated.\n"},"numPagesGenerated":{"type":"integer","readOnly":true,"description":"Number of pages generated by an export/page generator."},"doneExporting":{"type":"boolean","readOnly":true,"description":"Whether export/page generation is complete."},"numPagesProcessed":{"type":"integer","readOnly":true,"description":"Number of pages processed by downstream imports."},"oIndex":{"type":"integer","readOnly":true,"description":"Branch/router index for branched flows (if applicable)."},"retriable":{"type":"boolean","readOnly":true,"description":"Whether this job is eligible for retry."},"files":{"type":"array","readOnly":true,"description":"Files produced by the job (may be empty).","items":{"$ref":"#/components/schemas/JobFileRef"}},"logs":{"type":"array","readOnly":true,"description":"Log artifacts associated with the job (may be empty).","items":{"$ref":"#/components/schemas/JobLogRef"}},"errorFile":{"allOf":[{"$ref":"#/components/schemas/JobErrorFileRef"},{"description":"Error file artifact (if any)."}]},"logMode":{"type":"string","readOnly":true,"description":"Effective logging mode used for this job (derived from flow + account settings)."},"__lastPageGeneratorJob":{"type":"boolean","readOnly":true,"description":"Internal flag used by the UI for page-generator job handling."}}},"JobFileRef":{"type":"object","description":"Reference to a file produced by a job.","properties":{"id":{"type":"string","description":"File id in the underlying storage provider."},"host":{"type":"string","description":"Storage host/provider.","enum":["netsuite","s3"]},"name":{"type":"string","description":"Display name for the file (if available)."}}},"JobLogRef":{"type":"object","description":"Reference to a job log artifact.","properties":{"id":{"type":"string","description":"Log id in the underlying storage provider."},"host":{"type":"string","description":"Storage host/provider.","enum":["netsuite"]}}},"JobErrorFileRef":{"type":"object","description":"Reference to an error file produced by a job.","properties":{"id":{"type":"string","description":"Error file id in the underlying storage provider."},"host":{"type":"string","description":"Storage host/provider.","enum":["s3"]}}},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422-unprocessable-entity":{"description":"Unprocessable entity. The request was well-formed but was unable to be followed due to semantic errors.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/{_stepId}/retry":{"post":{"operationId":"retryFlowStepErrors","tags":["Flows"],"summary":"Retry errored records","description":"Re-runs the per-record data snapshots captured when the listed errors occurred. A successful retry\nauto-resolves the underlying open-error record. A retry that fails again stays open (and may\naccumulate error history, depending on the adaptor).\n\nOnly errors that carry a `retryDataKey` can be retried — typically these are record-level errors\nfrom imports or transforms. Connection-level errors (`classification: connection`) don't have a\n`retryDataKey`; to recover from those, re-run the whole flow after fixing the connection.\n\n**Response behavior splits on whether any key matched:**\n- At least one valid `retryDataKey` → **200** with a `type: \"retry\"` Job record (the queued retry\n  job; poll it via `GET /v1/jobs/{_id}`). A successful retry clears the original error from\n  `GET .../errors` and moves it into `/resolved` with `resolvedBy` set to the user who triggered\n  the retry (not `\"auto\"`, despite what older docs say).\n- No keys matched any stored snapshot → **204** silent no-op. There is no per-key validation: the\n  endpoint does not 400 on bogus keys; callers must poll `GET .../errors` to confirm any change.\n\n**Retry outcome semantics.** A retry that still fails generates a **new** error record with a new\n`errorId` (the original one is auto-resolved when the retry ultimately succeeds, or stays open\npending next retry). Building a UI on top of this endpoint needs to reconcile the \"before\" and\n\"after\" error lists by `retryDataKey`, not `errorId`.\n\nAI guidance:\n- To modify the record before retrying (e.g. fix a bad field), call\n  `GET /v1/flows/{_id}/{_stepId}/{retryDataKey}/data`, mutate the payload, `PUT` it back, **then**\n  call this endpoint.\n- Retrying a batch does not guarantee ordering relative to fresh incoming data; the retried records\n  go through the same page-processor pipeline as new records.\n- The CLI batches at 1000 per call; match that cap when building large retry sets.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_stepId","in":"path","required":true,"description":"Export or import id.","schema":{"type":"string","format":"objectId"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepRetryRequest"}}}},"responses":{"200":{"description":"Retry job queued. Body is the queued `type: \"retry\"` job record; poll it via\n`GET /v1/jobs/{_id}` to observe the retry's outcome.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"204":{"description":"None of the supplied `retryDataKeys` matched a stored snapshot — silent no-op. Poll\n`GET .../errors` to confirm state."},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"},"422":{"$ref":"#/components/responses/422-unprocessable-entity"}}}}}}
```

## Retry errored records with exponential back-off

> Re-runs errored record snapshots using an exponential decay (back-off) strategy. Behaves like\
> \`POST .../retry\` but schedules retries with increasing delays between attempts, reducing load\
> on the target system during transient outages.\
> \
> \*\*Response behavior splits on whether any key matched:\*\*\
> \- At least one valid \`retryDataKey\` → \*\*200\*\* with a full \`type: "retry"\` Job record.\
> \- No keys matched any stored snapshot → \*\*204\*\* silent no-op.\
> \
> The flow must be enabled (not disabled) — a disabled flow returns 422 \`inactive\_flow\`.\
> \
> AI guidance:\
> \- Prefer this over \`POST .../retry\` when errors are caused by rate-limiting or transient\
> &#x20; target-system issues — the exponential back-off avoids hammering the destination.\
> \- The resulting job can be polled via \`GET /v1/jobs/{\_id}\` just like a standard retry job.\
> \- Only errors with a \`retryDataKey\` can be retried. Connection-level errors lack one — rerun\
> &#x20; the whole flow to recover from those.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowStepRetryExponentialRequest":{"type":"object","description":"Request body for `POST /v1/flows/{_id}/{_stepId}/retry_with_exponential_decay`. Retries errored\nrecords using an exponential back-off strategy. Returns a Job object when at least one key\nmatched, or 204 if none matched.","properties":{"retryDataKeys":{"type":"array","description":"Opaque per-error snapshot keys. Same format as `POST .../retry`. Only errors that carry a\n`retryDataKey` can be retried.","minItems":1,"items":{"type":"string"}}},"required":["retryDataKeys"]},"Job":{"type":"object","description":"A job represents one execution of a flow/export/import (or a retry) in integrator.io.\nJobs are primarily read-only records created by the platform when executions occur.\n","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Job id."},"_userId":{"type":"string","format":"objectId","readOnly":true,"description":"Owner user id for the job."},"type":{"type":"string","readOnly":true,"description":"Job type.\n- `flow`: a flow run (parent job)\n- `export` / `import`: child jobs for an export/import step\n- `retry` / `bulk_retry`: error management retries\n","enum":["export","import","flow","retry","bulk_retry"]},"status":{"type":"string","readOnly":true,"description":"Current job status.","enum":["queued","running","retrying","completed","failed","canceled","canceling"]},"_integrationId":{"type":"string","format":"objectId","readOnly":true,"description":"Integration id this job belongs to (if applicable)."},"_flowId":{"type":"string","format":"objectId","readOnly":true,"description":"Flow id this job belongs to (if applicable)."},"_exportId":{"type":"string","format":"objectId","readOnly":true,"description":"Export id. Present on child export jobs and also on parent flow\njobs (where it references the first page-generator export)."},"_importId":{"type":"string","format":"objectId","readOnly":true,"description":"Import id for import child jobs (if applicable)."},"_expOrImpId":{"type":"string","format":"objectId","readOnly":true,"description":"Internal reference to an export/import for branched flows (if applicable)."},"_retryOfJobId":{"type":"string","format":"objectId","readOnly":true,"description":"If this is a retry job, the original job id being retried."},"_flowJobId":{"type":"string","format":"objectId","readOnly":true,"description":"Parent flow job id (for child jobs)."},"_parentJobId":{"type":"string","format":"objectId","readOnly":true,"description":"Parent job id (used for branched flows / hierarchy)."},"_bulkJobId":{"type":"string","format":"objectId","readOnly":true,"description":"Bulk retry parent job id (if applicable)."},"startedAt":{"type":"string","format":"date-time","readOnly":true,"description":"When execution started."},"endedAt":{"type":"string","format":"date-time","readOnly":true,"description":"When execution ended."},"resolvedAt":{"type":"string","format":"date-time","readOnly":true,"description":"When errors for the job were fully resolved (if applicable)."},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"When the job record was created."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Last modification time for the job record."},"lastExecutedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Last time the job executed work (may differ from createdAt/startedAt)."},"purgeAt":{"type":"string","format":"date-time","readOnly":true,"description":"When the job should be purged from primary storage."},"clickhousePurgeAt":{"type":"string","format":"date-time","readOnly":true,"description":"When the job should be purged from ClickHouse (if enabled)."},"triggeredBy":{"type":"string","readOnly":true,"description":"Who/what triggered the job (free-form string)."},"canceledBy":{"type":"string","readOnly":true,"description":"Who/what requested cancellation (free-form string)."},"flowExecutionGroupId":{"type":"string","readOnly":true,"description":"Groups multiple related jobs for a single flow execution."},"numError":{"type":"integer","readOnly":true,"description":"Total number of errors produced by the job (including resolved ones).\nUse `numOpenError` for the count of currently unresolved errors.\n"},"numOpenError":{"type":"integer","readOnly":true,"description":"Number of unresolved errors (equivalent to `numError - numResolved`).\nThis is the value dashboards surface as \"errors needing attention.\"\n"},"numResolved":{"type":"integer","readOnly":true,"description":"Number of resolved errors."},"numResolvedByAdaptor":{"type":"integer","readOnly":true,"description":"Number of errors resolved by the adaptor."},"numSuccess":{"type":"integer","readOnly":true,"description":"Number of successful records/pages."},"numIgnore":{"type":"integer","readOnly":true,"description":"Number of ignored records/pages."},"numExport":{"type":"integer","readOnly":true,"description":"Legacy field used by retry logic. May be deprecated.\n"},"numPagesGenerated":{"type":"integer","readOnly":true,"description":"Number of pages generated by an export/page generator."},"doneExporting":{"type":"boolean","readOnly":true,"description":"Whether export/page generation is complete."},"numPagesProcessed":{"type":"integer","readOnly":true,"description":"Number of pages processed by downstream imports."},"oIndex":{"type":"integer","readOnly":true,"description":"Branch/router index for branched flows (if applicable)."},"retriable":{"type":"boolean","readOnly":true,"description":"Whether this job is eligible for retry."},"files":{"type":"array","readOnly":true,"description":"Files produced by the job (may be empty).","items":{"$ref":"#/components/schemas/JobFileRef"}},"logs":{"type":"array","readOnly":true,"description":"Log artifacts associated with the job (may be empty).","items":{"$ref":"#/components/schemas/JobLogRef"}},"errorFile":{"allOf":[{"$ref":"#/components/schemas/JobErrorFileRef"},{"description":"Error file artifact (if any)."}]},"logMode":{"type":"string","readOnly":true,"description":"Effective logging mode used for this job (derived from flow + account settings)."},"__lastPageGeneratorJob":{"type":"boolean","readOnly":true,"description":"Internal flag used by the UI for page-generator job handling."}}},"JobFileRef":{"type":"object","description":"Reference to a file produced by a job.","properties":{"id":{"type":"string","description":"File id in the underlying storage provider."},"host":{"type":"string","description":"Storage host/provider.","enum":["netsuite","s3"]},"name":{"type":"string","description":"Display name for the file (if available)."}}},"JobLogRef":{"type":"object","description":"Reference to a job log artifact.","properties":{"id":{"type":"string","description":"Log id in the underlying storage provider."},"host":{"type":"string","description":"Storage host/provider.","enum":["netsuite"]}}},"JobErrorFileRef":{"type":"object","description":"Reference to an error file produced by a job.","properties":{"id":{"type":"string","description":"Error file id in the underlying storage provider."},"host":{"type":"string","description":"Storage host/provider.","enum":["s3"]}}},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/{_stepId}/retry_with_exponential_decay":{"post":{"operationId":"retryFlowStepErrorsWithExponentialDecay","tags":["Flows"],"summary":"Retry errored records with exponential back-off","description":"Re-runs errored record snapshots using an exponential decay (back-off) strategy. Behaves like\n`POST .../retry` but schedules retries with increasing delays between attempts, reducing load\non the target system during transient outages.\n\n**Response behavior splits on whether any key matched:**\n- At least one valid `retryDataKey` → **200** with a full `type: \"retry\"` Job record.\n- No keys matched any stored snapshot → **204** silent no-op.\n\nThe flow must be enabled (not disabled) — a disabled flow returns 422 `inactive_flow`.\n\nAI guidance:\n- Prefer this over `POST .../retry` when errors are caused by rate-limiting or transient\n  target-system issues — the exponential back-off avoids hammering the destination.\n- The resulting job can be polled via `GET /v1/jobs/{_id}` just like a standard retry job.\n- Only errors with a `retryDataKey` can be retried. Connection-level errors lack one — rerun\n  the whole flow to recover from those.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_stepId","in":"path","required":true,"description":"Export or import id.","schema":{"type":"string","format":"objectId"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepRetryExponentialRequest"}}}},"responses":{"200":{"description":"Retry job queued with exponential back-off. Body is the queued `type: \"retry\"` job record;\npoll it via `GET /v1/jobs/{_id}`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"204":{"description":"None of the supplied `retryDataKeys` matched a stored snapshot — silent no-op."},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"},"422":{"description":"Flow is disabled. Error code: `inactive_flow`. Enable the flow before retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
```

## Get the stored retry-data snapshot for an error

> Returns the per-record snapshot the runtime captured at the moment of failure — the shape that\
> \`POST .../retry\` re-feeds into the flow pipeline. The response is an envelope: \`data\` carries the\
> adaptor-specific record payload; surrounding fields (\`stage\`, \`pgExportId\`, \`oneToMany\`,\
> \`pathToMany\`, \`childIndex\`, \`traceKey\`) identify where in the pipeline the record was when it\
> failed and how it's structured.\
> \
> AI guidance:\
> \- This is the single most useful call when debugging a record-level failure: \`data\` shows \*exactly\*\
> &#x20; the payload the runtime tried to submit. Compare against what you see in the source system to\
> &#x20; pinpoint transformation drift.\
> \- Use \`PUT .../{retryDataKey}/data\` to mutate the snapshot before retrying — fix a malformed field\
> &#x20; and \`POST .../retry\` against the same \`retryDataKey\`.\
> \- Only errors that have a \`retryDataKey\` on the listing expose this endpoint — connection-class\
> &#x20; errors return 404 with \`{errors:\[{code:"no\_retrydata\_found",…}]}\`.\
> \- \`stage\` tells you \*where\* the retry will resume: \`page\_processor\_import\` means the retry re-runs\
> &#x20; the import with this payload (most common); \`page\_generator\` means the error was upstream of\
> &#x20; the processor.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowStepRetryData":{"type":"object","description":"Envelope around a per-record snapshot captured at the moment an error occurred. Returned by\n`GET /v1/flows/{_id}/{_stepId}/{retryDataKey}/data` and accepted (full-replace) by the PUT on the\nsame path.\n\nThe `data` field carries the actual record payload the runtime tried to submit — its shape is\nadaptor-specific. The surrounding fields identify where in the pipeline the failure happened and\nhow the record was structured.","properties":{"retryDataKey":{"type":"string","description":"Echoes the path parameter."},"data":{"description":"The opaque record payload. For HTTPImport errors this is the HTTP response the target system\nreturned; for data-level failures it's the record as seen by the step. Shape varies by adaptor.","additionalProperties":true},"stage":{"type":"string","description":"Pipeline stage where the record was when the error occurred.\n- `page_generator` — export produced the record but a downstream step failed.\n- `page_processor_import` — import stage failure (most common record-level retry path).\n- `page_processor_export` — lookup/export stage inside a page processor."},"pgExportId":{"type":"string","format":"objectId","description":"Id of the page-generator export that originated this record."},"oneToMany":{"type":"boolean","description":"Whether the stored record represents a one-to-many expansion. When `true`, `childIndex` and\n`pathToMany` locate the specific sub-record inside the parent payload."},"pathToMany":{"type":["string","null"],"description":"JSON-path / dot-path into the parent payload naming the array of sub-records. Null on one-to-one records."},"childIndex":{"type":["integer","null"],"description":"Zero-based index into the `pathToMany` array when `oneToMany: true`. Null on one-to-one records."},"traceKey":{"type":["string","null"],"description":"Trace identifier for cross-bubble stitching in execution logs. Populated when the source export\nhas a `traceKeyTemplate` configured."},"adaptorResponse":{"type":"object","additionalProperties":true,"description":"Adaptor-level response envelope captured alongside the record payload. Present on failures\nreturned by an HTTP or import adaptor; carries fields like `data[]`, `errors[]`,\n`subGroupIdMapForSuccess`, `resultRecordIds`, `dataURIs`, `groupId`, `recordId`,\nand `ignoredResults`. Treat the shape as opaque — it varies by adaptor — and pass it through\nunchanged when PUT-ing the envelope back."}},"required":["retryDataKey","data","stage","oneToMany"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}}},"paths":{"/v1/flows/{_id}/{_stepId}/{retryDataKey}/data":{"get":{"operationId":"getFlowStepErrorData","tags":["Flows"],"summary":"Get the stored retry-data snapshot for an error","description":"Returns the per-record snapshot the runtime captured at the moment of failure — the shape that\n`POST .../retry` re-feeds into the flow pipeline. The response is an envelope: `data` carries the\nadaptor-specific record payload; surrounding fields (`stage`, `pgExportId`, `oneToMany`,\n`pathToMany`, `childIndex`, `traceKey`) identify where in the pipeline the record was when it\nfailed and how it's structured.\n\nAI guidance:\n- This is the single most useful call when debugging a record-level failure: `data` shows *exactly*\n  the payload the runtime tried to submit. Compare against what you see in the source system to\n  pinpoint transformation drift.\n- Use `PUT .../{retryDataKey}/data` to mutate the snapshot before retrying — fix a malformed field\n  and `POST .../retry` against the same `retryDataKey`.\n- Only errors that have a `retryDataKey` on the listing expose this endpoint — connection-class\n  errors return 404 with `{errors:[{code:\"no_retrydata_found\",…}]}`.\n- `stage` tells you *where* the retry will resume: `page_processor_import` means the retry re-runs\n  the import with this payload (most common); `page_generator` means the error was upstream of\n  the processor.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_stepId","in":"path","required":true,"description":"Export or import id.","schema":{"type":"string","format":"objectId"}},{"name":"retryDataKey","in":"path","required":true,"description":"The `retryDataKey` from the error record.","schema":{"type":"string"}}],"responses":{"200":{"description":"The stored retry-data snapshot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepRetryData"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"description":"No snapshot exists for this key. Body: `{\"errors\":[{\"code\":\"no_retrydata_found\",\"message\":\"No\nretry data found for the given retryDataKey.\"}]}`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
```

## Update the stored retry-data snapshot for an error

> \*\*Full-replace\*\* of the stored per-record snapshot. The body becomes the new payload that\
> \`POST .../retry\` will feed back into the pipeline. Same envelope shape as the matching GET — send\
> the whole object (not just \`data\`), optionally mutated.\
> \
> AI guidance:\
> \- The round-trip pattern is: \`GET .../{retryDataKey}/data\` → mutate \`data\` locally → \`PUT\` the\
> &#x20; whole envelope back → \`POST .../retry\` with the same \`retryDataKey\`. The CLI's\
> &#x20; \`update-error-data\` command reads the modified envelope JSON from stdin for exactly this workflow.\
> \- Full replace — send the complete envelope, not a partial patch. Omitted fields are lost; the\
> &#x20; envelope's \`retryDataKey\`, \`stage\`, \`pgExportId\` fields must match what you got from the GET.\
> \- Editing the snapshot does \*\*not\*\* clear the error — the error stays open until a subsequent\
> &#x20; retry (or manual resolve) moves it.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowStepRetryData":{"type":"object","description":"Envelope around a per-record snapshot captured at the moment an error occurred. Returned by\n`GET /v1/flows/{_id}/{_stepId}/{retryDataKey}/data` and accepted (full-replace) by the PUT on the\nsame path.\n\nThe `data` field carries the actual record payload the runtime tried to submit — its shape is\nadaptor-specific. The surrounding fields identify where in the pipeline the failure happened and\nhow the record was structured.","properties":{"retryDataKey":{"type":"string","description":"Echoes the path parameter."},"data":{"description":"The opaque record payload. For HTTPImport errors this is the HTTP response the target system\nreturned; for data-level failures it's the record as seen by the step. Shape varies by adaptor.","additionalProperties":true},"stage":{"type":"string","description":"Pipeline stage where the record was when the error occurred.\n- `page_generator` — export produced the record but a downstream step failed.\n- `page_processor_import` — import stage failure (most common record-level retry path).\n- `page_processor_export` — lookup/export stage inside a page processor."},"pgExportId":{"type":"string","format":"objectId","description":"Id of the page-generator export that originated this record."},"oneToMany":{"type":"boolean","description":"Whether the stored record represents a one-to-many expansion. When `true`, `childIndex` and\n`pathToMany` locate the specific sub-record inside the parent payload."},"pathToMany":{"type":["string","null"],"description":"JSON-path / dot-path into the parent payload naming the array of sub-records. Null on one-to-one records."},"childIndex":{"type":["integer","null"],"description":"Zero-based index into the `pathToMany` array when `oneToMany: true`. Null on one-to-one records."},"traceKey":{"type":["string","null"],"description":"Trace identifier for cross-bubble stitching in execution logs. Populated when the source export\nhas a `traceKeyTemplate` configured."},"adaptorResponse":{"type":"object","additionalProperties":true,"description":"Adaptor-level response envelope captured alongside the record payload. Present on failures\nreturned by an HTTP or import adaptor; carries fields like `data[]`, `errors[]`,\n`subGroupIdMapForSuccess`, `resultRecordIds`, `dataURIs`, `groupId`, `recordId`,\nand `ignoredResults`. Treat the shape as opaque — it varies by adaptor — and pass it through\nunchanged when PUT-ing the envelope back."}},"required":["retryDataKey","data","stage","oneToMany"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}}},"paths":{"/v1/flows/{_id}/{_stepId}/{retryDataKey}/data":{"put":{"operationId":"updateFlowStepErrorData","tags":["Flows"],"summary":"Update the stored retry-data snapshot for an error","description":"**Full-replace** of the stored per-record snapshot. The body becomes the new payload that\n`POST .../retry` will feed back into the pipeline. Same envelope shape as the matching GET — send\nthe whole object (not just `data`), optionally mutated.\n\nAI guidance:\n- The round-trip pattern is: `GET .../{retryDataKey}/data` → mutate `data` locally → `PUT` the\n  whole envelope back → `POST .../retry` with the same `retryDataKey`. The CLI's\n  `update-error-data` command reads the modified envelope JSON from stdin for exactly this workflow.\n- Full replace — send the complete envelope, not a partial patch. Omitted fields are lost; the\n  envelope's `retryDataKey`, `stage`, `pgExportId` fields must match what you got from the GET.\n- Editing the snapshot does **not** clear the error — the error stays open until a subsequent\n  retry (or manual resolve) moves it.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_stepId","in":"path","required":true,"description":"Export or import id.","schema":{"type":"string","format":"objectId"}},{"name":"retryDataKey","in":"path","required":true,"description":"The `retryDataKey` from the error record.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepRetryData"}}}},"responses":{"204":{"description":"Snapshot updated (no body)."},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"description":"No snapshot exists for this key. Body: `{\"errors\":[{\"code\":\"no_retrydata_found\",\"message\":\"No\nretry data found for the given retryDataKey.\"}]}`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
```

## Get a signed URL to download file-type retry data

> Returns a pre-signed S3 URL for downloading the raw retry data file associated with an error.\
> This only works for \*\*file-type\*\* retry data (e.g. file-based exports/imports). For standard\
> record-based retry data, use \`GET .../{ retryDataKey}/data\` instead — this endpoint returns\
> 400 \`invalid\_operation\` for non-file retry data.\
> \
> AI guidance:\
> \- Check the error's adaptor type before calling this. File-based adaptors (FTP, S3, etc.)\
> &#x20; store retry data as files; record-based adaptors store JSON snapshots. Calling this on a\
> &#x20; record-based error returns 400.\
> \- The signed URL requires no auth headers — it's a plain S3 GET.\
> \- 404 \`no\_retrydata\_found\` is returned when the \`retryDataKey\` doesn't match any stored data.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowStepSignedURLResponse":{"type":"object","description":"Pre-signed S3 URL for downloading error or retry data as a CSV file. The URL expires after\napproximately 15 minutes. Returned by the `signedURL` endpoints on errors, resolved errors,\nand retry data.","properties":{"signedURL":{"type":"string","format":"uri","description":"Pre-signed S3 URL that streams a CSV file when fetched with a plain GET (no auth headers\nneeded). Expires ~15 minutes after generation. The CSV always includes a header row, even\nwhen there are zero matching records."}},"required":["signedURL"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}}},"paths":{"/v1/flows/{_id}/{_stepId}/{retryDataKey}/signedURL":{"get":{"operationId":"getFlowStepRetryDataSignedURL","tags":["Flows"],"summary":"Get a signed URL to download file-type retry data","description":"Returns a pre-signed S3 URL for downloading the raw retry data file associated with an error.\nThis only works for **file-type** retry data (e.g. file-based exports/imports). For standard\nrecord-based retry data, use `GET .../{ retryDataKey}/data` instead — this endpoint returns\n400 `invalid_operation` for non-file retry data.\n\nAI guidance:\n- Check the error's adaptor type before calling this. File-based adaptors (FTP, S3, etc.)\n  store retry data as files; record-based adaptors store JSON snapshots. Calling this on a\n  record-based error returns 400.\n- The signed URL requires no auth headers — it's a plain S3 GET.\n- 404 `no_retrydata_found` is returned when the `retryDataKey` doesn't match any stored data.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_stepId","in":"path","required":true,"description":"Export or import id.","schema":{"type":"string","format":"objectId"}},{"name":"retryDataKey","in":"path","required":true,"description":"The `retryDataKey` from the error record.","schema":{"type":"string"}}],"responses":{"200":{"description":"Pre-signed S3 URL for the retry data file.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepSignedURLResponse"}}}},"400":{"description":"The retry data for this key is not file-type. Use `GET .../{ retryDataKey}/data` for\nstandard record-based retry data. Error code: `invalid_operation`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"description":"No retry data found for the given key. Error code: `no_retrydata_found`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
```

## Get the HTTP request/response for an errored record

> Returns the decoded HTTP request and response the runtime captured at the moment an error occurred,\
> looked up by the opaque \`reqAndResKey\` found on each error in \`GET .../errors\`.\
> \
> Sensitive values are masked \*\*before\*\* storage — query-string credentials, \`Authorization\` headers,\
> OAuth bearer tokens, and similar are rendered as \`\*\*\*\*\*\*\*\*\`. You cannot recover the original values\
> from this endpoint.\
> \
> AI guidance:\
> \- Use this to reproduce a failure outside Celigo (paste the URL + headers into \`curl\` and mimic the\
> &#x20; method). Remember to substitute real credentials for the masked values.\
> \- The \`time\` and \`response.receivedAt\` fields are epoch milliseconds — useful for correlating with\
> &#x20; target-system logs.\
> \- Not every error has a stored trace — record-level errors from non-HTTP adaptors (e.g.\
> &#x20; NetSuiteDistributedImport SOAP errors) lack a \`reqAndResKey\`.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowStepRequestResponse":{"type":"object","description":"Decoded HTTP request / response pair captured for a flow-step error. Retrieved via\n`GET /v1/flows/{_id}/{_stepId}/requests/{reqAndResKey}`. Sensitive query-string and header values\n(credentials, access tokens) are masked with `********` before storage.","properties":{"request":{"type":"object","description":"The outbound HTTP request the runtime issued.","properties":{"method":{"type":"string","description":"HTTP method (`GET`, `POST`, …)."},"url":{"type":"string","description":"Full URL sent, with sensitive query-string values masked."},"headers":{"type":"object","description":"Headers sent with the request (sensitive values masked).","additionalProperties":{"type":"string"}},"body":{"type":"string","description":"Request body, when applicable. String for JSON/XML payloads, omitted for GETs without a body."}}},"response":{"type":"object","description":"The response the runtime received.","properties":{"statusCode":{"type":"integer","description":"HTTP status code."},"headers":{"type":"object","description":"Response headers.","additionalProperties":{"type":"string"}},"body":{"type":"string","description":"Response body as received. Typically a string (JSON/XML/text); binary responses are base64-encoded."},"receivedAt":{"type":"integer","format":"int64","description":"Epoch milliseconds when the response was received."}}},"key":{"type":"string","description":"Echoes the `reqAndResKey` path parameter."},"id":{"type":"string","description":"Internal storage id for this request/response pair."},"time":{"type":"integer","format":"int64","description":"Epoch milliseconds when this pair was stored."}},"required":["request","response","key"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}}},"paths":{"/v1/flows/{_id}/{_stepId}/requests/{reqAndResKey}":{"get":{"operationId":"getFlowStepRequestDetail","tags":["Flows"],"summary":"Get the HTTP request/response for an errored record","description":"Returns the decoded HTTP request and response the runtime captured at the moment an error occurred,\nlooked up by the opaque `reqAndResKey` found on each error in `GET .../errors`.\n\nSensitive values are masked **before** storage — query-string credentials, `Authorization` headers,\nOAuth bearer tokens, and similar are rendered as `********`. You cannot recover the original values\nfrom this endpoint.\n\nAI guidance:\n- Use this to reproduce a failure outside Celigo (paste the URL + headers into `curl` and mimic the\n  method). Remember to substitute real credentials for the masked values.\n- The `time` and `response.receivedAt` fields are epoch milliseconds — useful for correlating with\n  target-system logs.\n- Not every error has a stored trace — record-level errors from non-HTTP adaptors (e.g.\n  NetSuiteDistributedImport SOAP errors) lack a `reqAndResKey`.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_stepId","in":"path","required":true,"description":"Export or import id.","schema":{"type":"string","format":"objectId"}},{"name":"reqAndResKey","in":"path","required":true,"description":"The `reqAndResKey` value from the error record.","schema":{"type":"string"}}],"responses":{"200":{"description":"Decoded request/response pair.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepRequestResponse"}}}},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"description":"The key did not match any stored trace (purged, expired, or never captured). Error code:\n`file_not_found`; message: \"We are unable to find the file for the given fileName.\"\nAlso returned when the flow or step id is unknown (code: `invalid_ref`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
```

## List stored HTTP request/response traces for a flow step

> Returns a paginated list of HTTP request/response trace metadata for a flow step, filtered by\
> time window, status code, method, and/or pipeline stage. Each entry contains summary metadata —\
> use \`GET .../requests/{reqAndResKey}\` to fetch the full decoded request/response pair for a\
> specific trace.\
> \
> Pagination is via \`nextPageURL\`: each page shifts the \`time\_lte\` window backward by 600000 ms\
> (10 minutes). Follow \`nextPageURL\` until it's \`null\`.\
> \
> \*\*Important:\*\* Time parameters (\`time\_lte\`, \`time\_gt\`) must be epoch milliseconds (integers).\
> Passing ISO 8601 strings returns 422 \`invalid\_or\_missing\_field\`.\
> \
> AI guidance:\
> \- Use this to discover which HTTP calls a step made during a specific time window. Pair with\
> &#x20; \`GET .../requests/{reqAndResKey}\` to drill into individual request/response bodies.\
> \- \`statusCode\` is returned as a string, not an integer — filter accordingly.\
> \- \`stage\` identifies where in the pipeline the request was captured (e.g. \`export\`, \`import\`).\
> \- For oversized bodies stored in S3, follow up with\
> &#x20; \`GET .../requests/{key}/files/signedURL\` after inspecting the inline trace.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowStepRequestsListResponse":{"type":"object","description":"Paginated list of stored HTTP request/response trace metadata for a flow step. Returned by\n`GET /v1/flows/{_id}/{_stepId}/requests`. Follow `nextPageURL` for additional pages; each page\nadjusts the `time_lte` window by 600000 ms (10 minutes).","properties":{"requests":{"type":"array","description":"Trace metadata entries for the current page.","items":{"type":"object","properties":{"key":{"type":"string","description":"Opaque key identifying this request/response pair (the `reqAndResKey`)."},"time":{"type":"integer","format":"int64","description":"Epoch milliseconds when the request was captured."},"method":{"type":"string","description":"HTTP method used (`GET`, `POST`, `PUT`, etc.)."},"statusCode":{"type":"string","description":"HTTP status code as a string (e.g. `\"200\"`, `\"403\"`)."},"stage":{"type":"string","description":"Pipeline stage where the request was captured (e.g. `export`, `import`)."}},"required":["key","time","method","statusCode","stage"]}},"nextPageURL":{"type":["string","null"],"description":"Full URL for the next page of results, or `null` when there are no more pages. Each page\nshifts `time_lte` backward by 600000 ms (10 minutes)."}},"required":["requests","nextPageURL"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/{_stepId}/requests":{"get":{"operationId":"listFlowStepRequests","tags":["Flows"],"summary":"List stored HTTP request/response traces for a flow step","description":"Returns a paginated list of HTTP request/response trace metadata for a flow step, filtered by\ntime window, status code, method, and/or pipeline stage. Each entry contains summary metadata —\nuse `GET .../requests/{reqAndResKey}` to fetch the full decoded request/response pair for a\nspecific trace.\n\nPagination is via `nextPageURL`: each page shifts the `time_lte` window backward by 600000 ms\n(10 minutes). Follow `nextPageURL` until it's `null`.\n\n**Important:** Time parameters (`time_lte`, `time_gt`) must be epoch milliseconds (integers).\nPassing ISO 8601 strings returns 422 `invalid_or_missing_field`.\n\nAI guidance:\n- Use this to discover which HTTP calls a step made during a specific time window. Pair with\n  `GET .../requests/{reqAndResKey}` to drill into individual request/response bodies.\n- `statusCode` is returned as a string, not an integer — filter accordingly.\n- `stage` identifies where in the pipeline the request was captured (e.g. `export`, `import`).\n- For oversized bodies stored in S3, follow up with\n  `GET .../requests/{key}/files/signedURL` after inspecting the inline trace.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_stepId","in":"path","required":true,"description":"Export or import id.","schema":{"type":"string","format":"objectId"}},{"name":"time_lte","in":"query","required":false,"description":"Upper bound of the time window (inclusive), as epoch milliseconds. Defaults to now if\nomitted.","schema":{"type":"integer","format":"int64"}},{"name":"time_gt","in":"query","required":false,"description":"Lower bound of the time window (exclusive), as epoch milliseconds.","schema":{"type":"integer","format":"int64"}},{"name":"statusCode","in":"query","required":false,"description":"Filter to traces with this HTTP status code (e.g. `403`, `500`).","schema":{"type":"string"}},{"name":"method","in":"query","required":false,"description":"Filter to traces with this HTTP method (e.g. `GET`, `POST`).","schema":{"type":"string"}},{"name":"stage","in":"query","required":false,"description":"Filter to traces captured at this pipeline stage (e.g. `export`, `import`).","schema":{"type":"string"}}],"responses":{"200":{"description":"One page of request/response trace metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepRequestsListResponse"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"},"422":{"description":"Time parameters were passed as ISO strings instead of epoch milliseconds. Error code:\n`invalid_or_missing_field`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
```

## Delete stored HTTP request/response traces by key

> Permanently removes specific stored request+response pairs from the per-step trace cache. Despite\
> the un-parameterized path, this is \*\*not\*\* a blanket purge — the request body must name the exact\
> \`reqAndResKey\` values to delete (from the errors listing). After deletion, subsequent calls to\
> \`GET .../requests/{reqAndResKey}\` for the deleted keys return 404 (\`file\_not\_found\`).\
> \
> The live API \*\*requires \`Content-Type: application/json\`\*\* plus a non-empty \`keys\[]\` array. A\
> request with no body, \`{}\`, or \`{keys: \[]}\` rejects with 400 \`invalid\_url\` / \`"keys is not valid."\`.\
> \
> AI guidance:\
> \- Use this to clean up oversized / PII-bearing trace captures on errors you don't intend to retry.\
> \- The underlying error record in \`GET .../errors\` remains, but its \`reqAndResKey\` pointer now\
> &#x20; dangles. Resolve or delete the error separately if that's also intended.\
> \- To empty the whole cache for a step, enumerate the current errors, collect all \`reqAndResKey\`\
> &#x20; values, and pass them as \`keys\[]\` — there is no single "purge all" call.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowStepRequestsDeleteRequest":{"type":"object","description":"Request body for `DELETE /v1/flows/{_id}/{_stepId}/requests`. Targets specific stored\nrequest/response traces for deletion by their opaque `reqAndResKey` identifiers — this is **not** a\nblanket-purge endpoint despite the un-parameterized path.","properties":{"keys":{"type":"array","description":"`reqAndResKey` values to delete, as listed on each error from `GET /v1/flows/{_id}/{_stepId}/errors`.\nEmpty array rejects with 400 (`invalid_url` / \"keys is not valid\"); to purge everything, enumerate\nthe current errors' keys and send them.","minItems":1,"items":{"type":"string"}}},"required":["keys"]},"FlowStepRequestsDeleteResponse":{"type":"object","description":"Result of `DELETE /v1/flows/{_id}/{_stepId}/requests`. Lists which requested keys were deleted and\nany per-key errors the platform encountered.","properties":{"deleted":{"type":"array","description":"Keys that were successfully deleted. Subset of the request's `keys[]`.","items":{"type":"string"}},"errors":{"type":"array","description":"Per-key error objects for entries that failed to delete (already gone, permission, etc.). Empty\narray on fully-successful calls.","items":{"type":"object","additionalProperties":true}}},"required":["deleted","errors"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/{_stepId}/requests":{"delete":{"operationId":"deleteFlowStepRequests","tags":["Flows"],"summary":"Delete stored HTTP request/response traces by key","description":"Permanently removes specific stored request+response pairs from the per-step trace cache. Despite\nthe un-parameterized path, this is **not** a blanket purge — the request body must name the exact\n`reqAndResKey` values to delete (from the errors listing). After deletion, subsequent calls to\n`GET .../requests/{reqAndResKey}` for the deleted keys return 404 (`file_not_found`).\n\nThe live API **requires `Content-Type: application/json`** plus a non-empty `keys[]` array. A\nrequest with no body, `{}`, or `{keys: []}` rejects with 400 `invalid_url` / `\"keys is not valid.\"`.\n\nAI guidance:\n- Use this to clean up oversized / PII-bearing trace captures on errors you don't intend to retry.\n- The underlying error record in `GET .../errors` remains, but its `reqAndResKey` pointer now\n  dangles. Resolve or delete the error separately if that's also intended.\n- To empty the whole cache for a step, enumerate the current errors, collect all `reqAndResKey`\n  values, and pass them as `keys[]` — there is no single \"purge all\" call.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_stepId","in":"path","required":true,"description":"Export or import id.","schema":{"type":"string","format":"objectId"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepRequestsDeleteRequest"}}}},"responses":{"200":{"description":"Per-key deletion result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepRequestsDeleteResponse"}}}},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"},"415":{"description":"`Content-Type: application/json` header is missing."}}}}}}
```

## Get a signed URL for an oversized request/response body

> Returns a pre-signed S3 URL for downloading the full request or response body when it was too\
> large to store inline in the trace record. Most request/response pairs have inline bodies\
> accessible via \`GET .../requests/{reqAndResKey}\` — this endpoint is only needed for the subset\
> where the body was offloaded to S3 due to size.\
> \
> AI guidance:\
> \- Call \`GET .../requests/{reqAndResKey}\` first. If the \`request.body\` or \`response.body\` is\
> &#x20; truncated or missing, try this endpoint to fetch the full payload from S3.\
> \- Returns 422 \`missing\_bodykey\` when the request has an inline body (the common case) — this\
> &#x20; means there's nothing offloaded to download.\
> \- Returns 404 \`file\_not\_found\` when the S3 object has been purged or never existed.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowStepSignedURLResponse":{"type":"object","description":"Pre-signed S3 URL for downloading error or retry data as a CSV file. The URL expires after\napproximately 15 minutes. Returned by the `signedURL` endpoints on errors, resolved errors,\nand retry data.","properties":{"signedURL":{"type":"string","format":"uri","description":"Pre-signed S3 URL that streams a CSV file when fetched with a plain GET (no auth headers\nneeded). Expires ~15 minutes after generation. The CSV always includes a header row, even\nwhen there are zero matching records."}},"required":["signedURL"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}}},"paths":{"/v1/flows/{_id}/{_stepId}/requests/{key}/files/signedURL":{"get":{"operationId":"getFlowStepRequestFilesSignedURL","tags":["Flows"],"summary":"Get a signed URL for an oversized request/response body","description":"Returns a pre-signed S3 URL for downloading the full request or response body when it was too\nlarge to store inline in the trace record. Most request/response pairs have inline bodies\naccessible via `GET .../requests/{reqAndResKey}` — this endpoint is only needed for the subset\nwhere the body was offloaded to S3 due to size.\n\nAI guidance:\n- Call `GET .../requests/{reqAndResKey}` first. If the `request.body` or `response.body` is\n  truncated or missing, try this endpoint to fetch the full payload from S3.\n- Returns 422 `missing_bodykey` when the request has an inline body (the common case) — this\n  means there's nothing offloaded to download.\n- Returns 404 `file_not_found` when the S3 object has been purged or never existed.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_stepId","in":"path","required":true,"description":"Export or import id.","schema":{"type":"string","format":"objectId"}},{"name":"key","in":"path","required":true,"description":"The `reqAndResKey` value from the request trace.","schema":{"type":"string"}}],"responses":{"200":{"description":"Pre-signed S3 URL for the oversized body file.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepSignedURLResponse"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"description":"The S3 file does not exist — it was purged or was never offloaded. Error code:\n`file_not_found`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request/response pair has an inline body — there is no offloaded file to download.\nError code: `missing_bodykey`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
```

## Set tags on a batch of errors

> \*\*Full-replace\*\* per-error: for each \`(errorId, retryDataKey)\` in the body, the stored tag set is\
> replaced with \`tagIds\`. Pass \`tagIds: \[]\` to clear all tags from the listed errors.\
> \
> Tags are account-scoped short codes (from \`GET /v1/tags\`) — not free-form strings. The \`tagId\` you\
> send here is the short code (e.g. \`F3ZBQ\`), \*\*not\*\* the tag document's Mongo \`\_id\`.\
> \
> AI guidance:\
> \- The errors batch uses short keys (\`id\` = errorId, \`rdk\` = retryDataKey) to minimize body size when\
> &#x20; retagging large sets. Both come straight off the \`GET .../errors\` listing.\
> \- Use \`rdk: ""\` (empty string) for errors without a \`retryDataKey\` (connection-class errors).\
> \- This endpoint replaces tags — there is no partial-update shape. To add a tag without removing\
> &#x20; existing ones, merge client-side first (fetch error, union tag codes, send full set).

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowStepTagsRequest":{"type":"object","description":"Request body for `PUT /v1/flows/{_id}/{_stepId}/tags`. Replaces the tag set on each listed error\nwith `tagIds`. Pass an empty `tagIds` array to clear all tags from the listed errors.","properties":{"errors":{"type":"array","description":"Error identifiers to retag. Each entry pairs an `errorId` with its opaque `retryDataKey` (when\npresent). Both fields from the `GET .../errors` response.","minItems":1,"items":{"type":"object","properties":{"id":{"type":"string","description":"Error id (`errorId` from the listing)."},"rdk":{"type":"string","description":"Retry data key (`retryDataKey` from the listing). Empty string or omitted when the error has none."}},"required":["id"]}},"tagIds":{"type":"array","description":"Short tag codes to apply. Obtain from `GET /v1/tags` — use the short `tagId` field (e.g.\n`F3ZBQ`), not the Mongo `_id`. Pass `[]` to remove all tags from the listed errors.","items":{"type":"string"}}},"required":["errors","tagIds"]},"FlowStepTagsResponse":{"type":"object","description":"Echo of which error records the tag mutation touched, split by their current state. Returned by\n`PUT /v1/flows/{_id}/{_stepId}/tags`.","properties":{"errorsToReturn":{"type":"object","description":"Ids split by whether each error was open or already resolved when retagged.","properties":{"errors":{"type":"array","description":"Ids of **open** errors that were retagged.","items":{"type":"string"}},"resolved":{"type":"array","description":"Ids of **resolved** errors that were retagged.","items":{"type":"string"}}},"required":["errors","resolved"]}},"required":["errorsToReturn"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/{_stepId}/tags":{"put":{"operationId":"updateFlowStepErrorTags","tags":["Flows"],"summary":"Set tags on a batch of errors","description":"**Full-replace** per-error: for each `(errorId, retryDataKey)` in the body, the stored tag set is\nreplaced with `tagIds`. Pass `tagIds: []` to clear all tags from the listed errors.\n\nTags are account-scoped short codes (from `GET /v1/tags`) — not free-form strings. The `tagId` you\nsend here is the short code (e.g. `F3ZBQ`), **not** the tag document's Mongo `_id`.\n\nAI guidance:\n- The errors batch uses short keys (`id` = errorId, `rdk` = retryDataKey) to minimize body size when\n  retagging large sets. Both come straight off the `GET .../errors` listing.\n- Use `rdk: \"\"` (empty string) for errors without a `retryDataKey` (connection-class errors).\n- This endpoint replaces tags — there is no partial-update shape. To add a tag without removing\n  existing ones, merge client-side first (fetch error, union tag codes, send full set).","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_stepId","in":"path","required":true,"description":"Export or import id.","schema":{"type":"string","format":"objectId"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepTagsRequest"}}}},"responses":{"200":{"description":"Tags updated. Body echoes affected ids split by current state (open vs resolved).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowStepTagsResponse"}}}},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Delete execution logs for a flow within a time range

> Asynchronously deletes execution-log entries for the flow that fall within the specified time range.\
> Returns \`202 Accepted\` with an empty body — the deletion runs in the background.\
> \
> Both \`startedAt\` and \`endAt\` are required query parameters and must be valid ISO 8601 datetime strings.\
> \`startedAt\` must be strictly before \`endAt\`; the server returns \`400 invalid\_query\_params\` otherwise.\
> \
> AI guidance:\
> \- This is a destructive, irreversible operation — once deleted, log data cannot be recovered.\
> \- Use this to reclaim storage or purge logs after a known-bad run window.\
> \- The 202 response does not include a job id; there is no way to poll for completion.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/logs":{"delete":{"operationId":"deleteFlowLogs","tags":["Flows"],"summary":"Delete execution logs for a flow within a time range","description":"Asynchronously deletes execution-log entries for the flow that fall within the specified time range.\nReturns `202 Accepted` with an empty body — the deletion runs in the background.\n\nBoth `startedAt` and `endAt` are required query parameters and must be valid ISO 8601 datetime strings.\n`startedAt` must be strictly before `endAt`; the server returns `400 invalid_query_params` otherwise.\n\nAI guidance:\n- This is a destructive, irreversible operation — once deleted, log data cannot be recovered.\n- Use this to reclaim storage or purge logs after a known-bad run window.\n- The 202 response does not include a job id; there is no way to poll for completion.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"startedAt","in":"query","required":true,"description":"Start of the time range (inclusive). ISO 8601 datetime. Must be before `endAt`.","schema":{"type":"string","format":"date-time"}},{"name":"endAt","in":"query","required":true,"description":"End of the time range (inclusive). ISO 8601 datetime. Must be after `startedAt`.","schema":{"type":"string","format":"date-time"}}],"responses":{"202":{"description":"Accepted — log deletion is running asynchronously."},"400":{"description":"Missing or invalid query parameters. Returned when `startedAt` or `endAt` is absent, not a valid\nISO datetime, or when `startedAt` is not before `endAt`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Cancel all running jobs for a flow

> Cancels every currently running job for the specified flow. This is the flow-scoped equivalent\
> of cancelling individual jobs via \`PUT /v1/jobs/{\_id}\` — it finds all in-progress jobs for the\
> flow and requests cancellation in a single call.\
> \
> No request body is required. The response is an empty 204 on success.\
> \
> AI guidance:\
> \- Use this when a flow is stuck or producing bad data and you need to stop all active\
> &#x20; processing immediately. Follow up with error inspection (\`GET /v1/flows/{\_id}/errors\`)\
> &#x20; to understand what was in flight.\
> \- Cancellation is asynchronous — jobs may take a few seconds to fully stop after the 204\
> &#x20; is returned.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}}},"paths":{"/v1/flows/{_id}/jobs/cancel":{"post":{"operationId":"cancelFlowJobs","tags":["Flows"],"summary":"Cancel all running jobs for a flow","description":"Cancels every currently running job for the specified flow. This is the flow-scoped equivalent\nof cancelling individual jobs via `PUT /v1/jobs/{_id}` — it finds all in-progress jobs for the\nflow and requests cancellation in a single call.\n\nNo request body is required. The response is an empty 204 on success.\n\nAI guidance:\n- Use this when a flow is stuck or producing bad data and you need to stop all active\n  processing immediately. Follow up with error inspection (`GET /v1/flows/{_id}/errors`)\n  to understand what was in flight.\n- Cancellation is asynchronous — jobs may take a few seconds to fully stop after the 204\n  is returned.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}}],"responses":{"204":{"description":"Cancellation requested for all running jobs. No response body."},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Search jobs within a flow by trace key

> Searches for flow-run jobs that contain records matching a trace key prefix. Returns up to 1000\
> matching job objects — there is no pagination beyond that limit.\
> \
> The \`traceKeyPrefix\` query parameter is required; the server returns \`400\` when it is missing.\
> \
> Known behavior: the \`status\` filter is accepted but silently ignored — the response always includes\
> jobs of all statuses regardless of the filter value.\
> \
> AI guidance:\
> \- Use this to find which job(s) processed a specific record when the caller knows the trace key\
> &#x20; (e.g. a Salesforce record id or NetSuite internal id used as the trace key).\
> \- Narrow the window with \`createdAt\_gte\` / \`createdAt\_lte\` when there are many runs for the flow.\
> \- Because \`status\` is silently ignored, filter client-side if you need only completed or errored jobs.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowJobsSearchResponse":{"type":"object","description":"Response for a flow-job search by trace key. Returns up to 1000 matching job objects.\nThere is no pagination — the result set is capped at 1000.","properties":{"runs":{"type":"array","description":"Matching job objects.","items":{"type":"object","description":"A flow-run job summary.","properties":{"_id":{"type":"string","format":"objectId","description":"Job id."},"_flowId":{"type":"string","format":"objectId","description":"Flow id that owns this job."},"type":{"type":"string","description":"Job type — always `flow` for flow-run jobs."},"status":{"type":"string","description":"Terminal status of the job."},"startedAt":{"type":"string","format":"date-time","description":"When the job started."},"endedAt":{"type":"string","format":"date-time","description":"When the job finished."},"numSuccess":{"type":"integer","description":"Count of records that completed successfully."},"numError":{"type":"integer","description":"Count of records that errored."},"numIgnore":{"type":"integer","description":"Count of records that were ignored (filtered out)."}}}}},"required":["runs"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/jobs/search":{"get":{"operationId":"searchFlowJobs","tags":["Flows"],"summary":"Search jobs within a flow by trace key","description":"Searches for flow-run jobs that contain records matching a trace key prefix. Returns up to 1000\nmatching job objects — there is no pagination beyond that limit.\n\nThe `traceKeyPrefix` query parameter is required; the server returns `400` when it is missing.\n\nKnown behavior: the `status` filter is accepted but silently ignored — the response always includes\njobs of all statuses regardless of the filter value.\n\nAI guidance:\n- Use this to find which job(s) processed a specific record when the caller knows the trace key\n  (e.g. a Salesforce record id or NetSuite internal id used as the trace key).\n- Narrow the window with `createdAt_gte` / `createdAt_lte` when there are many runs for the flow.\n- Because `status` is silently ignored, filter client-side if you need only completed or errored jobs.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"traceKeyPrefix","in":"query","required":true,"description":"Trace key prefix to search for. The server matches job records whose `traceKey` begins with this value.","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"Job status filter. **Note:** this parameter is currently accepted but silently ignored — all\nstatuses are always returned.","schema":{"type":"string"}},{"name":"createdAt_gte","in":"query","required":false,"description":"Only return jobs created at or after this ISO 8601 datetime.","schema":{"type":"string","format":"date-time"}},{"name":"createdAt_lte","in":"query","required":false,"description":"Only return jobs created at or before this ISO 8601 datetime.","schema":{"type":"string","format":"date-time"}},{"name":"pageSize","in":"query","required":false,"description":"Maximum number of jobs to return. Capped at 1000.","schema":{"type":"integer","minimum":1,"maximum":1000}}],"responses":{"200":{"description":"Matching job objects (max 1000).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowJobsSearchResponse"}}}},"400":{"description":"Missing required `traceKeyPrefix` query parameter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## List execution log entries for a flow run

> Returns one page of execution-log entries for a specific flow run — one entry per record-at-step\
> (export or import). Entries carry the \`(\_expOrImpId, groupId, recordId, traceKey)\` tuple needed to\
> drill into per-stage metadata and data via the \`logs/metadata/query\` and \`logs/data/query\` endpoints.\
> \
> Execution logs are populated only when the flow has logging enabled (either full \`logMode\` or the\
> time-bounded \`logging.debugUntil\` debug window). Jobs older than the flow's log retention window will\
> return an empty \`logs\` array.\
> \
> Pagination is body-driven: follow \`nextPageUrl\` until it is \`null\`. The URL may be absolute or a relative\
> path; strip the origin before re-requesting against this API.\
> \
> AI guidance:\
> \- Use this to answer "what records did this run process and which step did each end up at?"\
> \- For detailed per-stage data (HTTP request/response, script \`options.logs\` output), pick an entry and\
> &#x20; call \`POST .../logs/data/query\` with the corresponding \`stage\`.\
> \- To stitch an export entry to its downstream import entries, use the \`traceKey\` with\
> &#x20; \`POST .../logs/metadata/query\` — it returns a traceView across paired steps.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"ExecutionLogsResponse":{"type":"object","description":"One page of execution-log entries for a flow run. Pagination is body-driven: follow `nextPageUrl`\nto fetch the next page (null when the page is the last). `prevPageUrl` is populated for navigation\nbackward from a mid-history page.","properties":{"logs":{"type":"array","description":"Log entries in this page. Ordered newest-first.","items":{"$ref":"#/components/schemas/ExecutionLogEntry"}},"nextPageUrl":{"type":["string","null"],"description":"URL (absolute or path-relative) for the next page, or `null` on the last page."},"prevPageUrl":{"type":["string","null"],"description":"URL for the previous page, or `null` when already at the head."}},"required":["logs"]},"ExecutionLogEntry":{"type":"object","description":"One entry in a flow-run's execution log. Each entry represents a single record processed by a single step\n(export or import) and carries the identifiers needed to drill into per-stage traces via\n`POST /v1/flows/{_id}/jobs/{_jobId}/logs/metadata/query` and `.../logs/data/query`.\n\nThe tuple `(_expOrImpId, groupId, recordId)` uniquely identifies the record-at-step; `traceKey` groups\nthe paired export and import entries that processed the same record end-to-end.","properties":{"startedAt":{"type":"string","format":"date-time","description":"When this step began processing the record."},"recordId":{"type":"string","description":"Opaque per-record identifier. Feed this (together with `groupId` and `_expOrImpId`) into the metadata/data query endpoints."},"groupId":{"type":"string","description":"Opaque batch identifier — records processed in the same page/batch share a groupId."},"traceKey":{"type":"string","description":"Trace identifier that pairs an export entry with the import entries that processed its output.\nPass as `traceKey` to `metadata/query` to get a traceView across paired steps."},"_expOrImpId":{"type":"string","format":"objectId","description":"Id of the export or import step that produced this entry."},"status":{"type":"string","description":"Outcome of this step for this record.","enum":["success","error","ignored"]},"timeTaken":{"type":"integer","description":"Milliseconds spent processing this record at this step."}},"required":["recordId","groupId","_expOrImpId","status"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/jobs/{_jobId}/logs":{"get":{"operationId":"listFlowExecutionLogs","tags":["Flows"],"summary":"List execution log entries for a flow run","description":"Returns one page of execution-log entries for a specific flow run — one entry per record-at-step\n(export or import). Entries carry the `(_expOrImpId, groupId, recordId, traceKey)` tuple needed to\ndrill into per-stage metadata and data via the `logs/metadata/query` and `logs/data/query` endpoints.\n\nExecution logs are populated only when the flow has logging enabled (either full `logMode` or the\ntime-bounded `logging.debugUntil` debug window). Jobs older than the flow's log retention window will\nreturn an empty `logs` array.\n\nPagination is body-driven: follow `nextPageUrl` until it is `null`. The URL may be absolute or a relative\npath; strip the origin before re-requesting against this API.\n\nAI guidance:\n- Use this to answer \"what records did this run process and which step did each end up at?\"\n- For detailed per-stage data (HTTP request/response, script `options.logs` output), pick an entry and\n  call `POST .../logs/data/query` with the corresponding `stage`.\n- To stitch an export entry to its downstream import entries, use the `traceKey` with\n  `POST .../logs/metadata/query` — it returns a traceView across paired steps.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_jobId","in":"path","required":true,"description":"Flow-run job id (the `_id` of a `type: \"flow\"` job).","schema":{"type":"string","format":"objectId"}},{"name":"status","in":"query","required":false,"description":"Filter log entries by record outcome.","schema":{"type":"string","enum":["success","error","ignore"]}},{"name":"_expOrImpId","in":"query","required":false,"description":"Comma-separated list of export or import step ids. Only entries produced by these steps are returned.","schema":{"type":"string"}},{"name":"traceKeyPrefix","in":"query","required":false,"description":"Filter entries whose `traceKey` starts with this prefix.","schema":{"type":"string"}},{"name":"sortOrder","in":"query","required":false,"description":"Sort direction for log entries by `startedAt`. Defaults to descending (newest first).","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"pageSize","in":"query","required":false,"description":"Number of log entries per page. Must be between 1 and 1000.","schema":{"type":"integer","minimum":1,"maximum":1000}}],"responses":{"200":{"description":"One page of execution-log entries.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecutionLogsResponse"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Query execution-log metadata for a record-at-step

> Returns per-step timing and outcome metadata for a single record as it traveled through a flow run.\
> When the request includes \`traceKey\`, the response spans every step that shared that trace — typically\
> the source export plus its downstream imports.\
> \
> Pull the \`\_expOrImpId\`, \`groupId\`, \`recordId\`, and (optionally) \`traceKey\` values from a\
> \`GET /v1/flows/{\_id}/jobs/{\_jobId}/logs\` entry.\
> \
> AI guidance:\
> \- Pair this with \`logs/data/query\` to build a full per-record trace: this endpoint tells you \*which\* steps\
> &#x20; were touched and how long each took; the data endpoint returns the actual payload at each stage.\
> \- Watch for \`duplicateTraceKey: true\` — it means the traceKey was seen on more than one record in the job,\
> &#x20; so a traceView built from it may mix records that got retried or fanned out.\
> \- Without \`traceKey\` in the request, \`traceView\` is \`false\` and only the single queried step is returned.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"ExecutionLogMetadataRequest":{"type":"object","description":"Request body for `POST /v1/flows/{_id}/jobs/{_jobId}/logs/metadata/query`.\nIdentifies a single record-at-step within the job's execution log. Include `traceKey` to widen\nthe result to every step that shared that trace (export paired with its downstream imports).","properties":{"_expOrImpId":{"type":"string","format":"objectId","description":"Id of the export or import step the record was processed by."},"groupId":{"type":"string","description":"The `groupId` from the matching `execution-log` entry."},"recordId":{"type":"string","description":"The `recordId` from the matching `execution-log` entry."},"traceKey":{"type":"string","description":"Optional. When provided, the response includes a `traceView` across every step that shared this trace key\n(e.g. the original export plus its downstream imports)."}},"required":["_expOrImpId","groupId","recordId"]},"ExecutionLogMetadataResponse":{"type":"object","description":"Metadata for a single record-at-step (or for every step sharing a `traceKey` when the request supplied one).\nReturned by `POST /v1/flows/{_id}/jobs/{_jobId}/logs/metadata/query`.","properties":{"traceKey":{"type":"string","description":"Echoed back when the request supplied a `traceKey`; omitted otherwise."},"duplicateTraceKey":{"type":"boolean","description":"`true` when the same traceKey was seen on more than one record in this job — useful for spotting\nrecords that got retried or fanned out and may need disambiguation when rendering the trace view."},"traceView":{"type":"boolean","description":"`true` when the response contains a multi-step trace (i.e. the request supplied `traceKey` and paired\nsteps were found). `false` when the response is scoped to the single queried step."},"steps":{"type":"array","description":"Per-step metadata. A single entry when `traceView` is false; one per paired step otherwise.","items":{"$ref":"#/components/schemas/ExecutionLogStep"}}},"required":["duplicateTraceKey","traceView","steps"]},"ExecutionLogStep":{"type":"object","description":"Per-step timing and outcome for a single record as it passed through one export or import.","properties":{"_expOrImpId":{"type":"string","format":"objectId","description":"Id of the export or import step."},"recordId":{"type":"string","description":"Opaque per-record id; pair with `groupId` + `_expOrImpId` when fetching stage data."},"groupId":{"type":"string","description":"Opaque batch id."},"status":{"type":"string","description":"Outcome at this step.","enum":["success","error","ignored"]},"timeTaken":{"type":"integer","description":"Milliseconds spent at this step for this record."},"startedAt":{"type":"string","description":"Step start time. Format is `YYYY-MM-DD HH:MM:SS.sss` (no `T`, no `Z`)."},"completedAt":{"type":"string","description":"Step completion time. Same format as `startedAt`."},"stage":{"type":"string","description":"Pipeline stage at which this step entry was recorded. Observed values include `apiCall`\n(the adaptor invocation itself). Useful for filtering metadata responses when a step has\nmultiple stage entries across a single record's pass."}},"required":["_expOrImpId","recordId","groupId","status"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/jobs/{_jobId}/logs/metadata/query":{"post":{"operationId":"queryFlowExecutionLogMetadata","tags":["Flows"],"summary":"Query execution-log metadata for a record-at-step","description":"Returns per-step timing and outcome metadata for a single record as it traveled through a flow run.\nWhen the request includes `traceKey`, the response spans every step that shared that trace — typically\nthe source export plus its downstream imports.\n\nPull the `_expOrImpId`, `groupId`, `recordId`, and (optionally) `traceKey` values from a\n`GET /v1/flows/{_id}/jobs/{_jobId}/logs` entry.\n\nAI guidance:\n- Pair this with `logs/data/query` to build a full per-record trace: this endpoint tells you *which* steps\n  were touched and how long each took; the data endpoint returns the actual payload at each stage.\n- Watch for `duplicateTraceKey: true` — it means the traceKey was seen on more than one record in the job,\n  so a traceView built from it may mix records that got retried or fanned out.\n- Without `traceKey` in the request, `traceView` is `false` and only the single queried step is returned.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_jobId","in":"path","required":true,"description":"Flow-run job id.","schema":{"type":"string","format":"objectId"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecutionLogMetadataRequest"}}}},"responses":{"200":{"description":"Step metadata (or a trace across paired steps when `traceKey` was supplied).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecutionLogMetadataResponse"}}}},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Get per-stage execution log data for a record

> Returns the decoded log data (typically request/response bodies, transform input/output, or script\
> \`options.logs\` entries) for a single \`(step, stage)\` tuple within a flow run.\
> \
> Stages are bubble-kind specific. The most useful values:\
> \- \*\*Export / Lookup:\*\* \`apiCall\` (HTTP request+response for HTTP exports), \`transformation\`,\
> &#x20; \`outputFilter\`, \`responseMapping\`.\
> \- \*\*Import:\*\* \`apiCall\`, \`mapping\`, \`inputFilter\`, \`responseTransformation\`.\
> \- \*\*Router:\*\* \`routing\` (branching decision).\
> \- \*\*Any:\*\* the \`function\` name from a configured script hook (e.g. \`preMap\`, \`postMap\`, \`postSubmit\`,\
> &#x20; \`postResponseMap\`, \`preSavePage\`) — populated only when the hook explicitly calls\
> &#x20; \`options.logs.push(...)\`.\
> \
> AI guidance:\
> \- Use this as the terminal call in the drill-down: \`execution-logs\` → \`metadata/query\` → \`data/query\`.\
> \- For HTTP traces (what the integrator.io runtime actually sent/received), set \`stage: apiCall\`.\
> \- A 200 with \`logs: \[]\` means the bubble ran the stage but produced no log entry — usually because\
> &#x20; the script did not call \`options.logs.push()\`, or the stage is not instrumented for that adaptor.\
> \- The top-level \`errors\[]\` may carry failures that are query-scoped rather than per-stage (e.g.\
> &#x20; NetSuiteDistributedImport attaches its real error to the response rather than to the log).

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"ExecutionLogDataRequest":{"type":"object","description":"Request body for `POST /v1/flows/{_id}/jobs/{_jobId}/logs/data/query`.\nFetches the actual data captured at a specific execution stage for a single record-at-step.","properties":{"_expOrImpId":{"type":"string","format":"objectId","description":"Id of the export or import step the record was processed by."},"stage":{"type":"string","description":"Execution stage whose data to return.\n\n- `apiCall` — raw HTTP request + response for HTTPExport / HTTPImport steps (most common).\n- `preMap`, `postMap`, `postSubmit`, `postResponseMap` — populated only when the corresponding\n  script hook called `options.logs.push(...)`. Otherwise returns `{logs: []}`.","enum":["apiCall","preMap","postMap","postSubmit","postResponseMap","transform","responseTransform"]},"groupId":{"type":"string","description":"Batch id from the `execution-log` entry."},"recordId":{"type":"string","description":"Record id from the `execution-log` entry."}},"required":["_expOrImpId","stage","groupId","recordId"]},"ExecutionLogDataResponse":{"type":"object","description":"Stage data for a single record-at-step. Returned by\n`POST /v1/flows/{_id}/jobs/{_jobId}/logs/data/query`.\n\nThe payload inside `logs[].log` is stage-specific. For `apiCall`, it contains decoded request + response\nbodies, headers, status, and duration. For script-hook stages (`preMap`, `postMap`, …), it contains\nwhatever the hook pushed via `options.logs.push(...)`, and is empty (`logs: []`) when the hook did not log.","properties":{"logs":{"type":"array","description":"Array of stage-data entries. Usually length 1 when data is available, 0 otherwise.","items":{"type":"object","properties":{"log":{"type":"object","description":"The stage payload. Fields depend on `stage`:\n- `apiCall`: request, response, status, headers, durationMs, …\n- script hooks: arbitrary keys the hook pushed via `options.logs.push(...)`.","additionalProperties":true}}}},"errors":{"type":"array","description":"Query-scoped errors. Some adaptors (e.g. NetSuiteDistributedImport) attach the actual failure here rather\nthan inside `logs[].log.errors`. Empty on success.","items":{"type":"object","additionalProperties":true}}},"required":["logs"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/jobs/{_jobId}/logs/data/query":{"post":{"operationId":"queryFlowExecutionLogData","tags":["Flows"],"summary":"Get per-stage execution log data for a record","description":"Returns the decoded log data (typically request/response bodies, transform input/output, or script\n`options.logs` entries) for a single `(step, stage)` tuple within a flow run.\n\nStages are bubble-kind specific. The most useful values:\n- **Export / Lookup:** `apiCall` (HTTP request+response for HTTP exports), `transformation`,\n  `outputFilter`, `responseMapping`.\n- **Import:** `apiCall`, `mapping`, `inputFilter`, `responseTransformation`.\n- **Router:** `routing` (branching decision).\n- **Any:** the `function` name from a configured script hook (e.g. `preMap`, `postMap`, `postSubmit`,\n  `postResponseMap`, `preSavePage`) — populated only when the hook explicitly calls\n  `options.logs.push(...)`.\n\nAI guidance:\n- Use this as the terminal call in the drill-down: `execution-logs` → `metadata/query` → `data/query`.\n- For HTTP traces (what the integrator.io runtime actually sent/received), set `stage: apiCall`.\n- A 200 with `logs: []` means the bubble ran the stage but produced no log entry — usually because\n  the script did not call `options.logs.push()`, or the stage is not instrumented for that adaptor.\n- The top-level `errors[]` may carry failures that are query-scoped rather than per-stage (e.g.\n  NetSuiteDistributedImport attaches its real error to the response rather than to the log).","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_jobId","in":"path","required":true,"description":"Flow-run job id.","schema":{"type":"string","format":"objectId"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecutionLogDataRequest"}}}},"responses":{"200":{"description":"Log entries for the requested `(step, stage)`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecutionLogDataResponse"}}}},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## List child log records for a parent record

> Returns one page of child log records for a specific parent record within a flow-run step.\
> Child records represent sub-operations (e.g. individual batch items, lookup expansions, or\
> retry attempts) spawned by the parent record during step processing.\
> \
> Pagination is body-driven: follow \`nextPageUrl\` / \`prevPageUrl\` until they are \`null\`.\
> Pagination cursors use \`offset\` (numeric) and \`next\`/\`prev\` (ISO timestamp) parameters\
> embedded in the URL.\
> \
> AI guidance:\
> \- Use this to drill into fan-out or batch-split scenarios where one parent record produces\
> &#x20; multiple child operations at a step.\
> \- Filter by \`status\` to isolate failures within a batch.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"FlowJobLogChildrenResponse":{"type":"object","description":"Paginated response for child log records of a parent record. Follow `nextPageUrl` to fetch\nsubsequent pages; `prevPageUrl` navigates backward. Both are `null` when at the boundary.","properties":{"children":{"type":"array","description":"Child log entries in this page.","items":{"$ref":"#/components/schemas/FlowJobLogEntry"}},"nextPageUrl":{"type":["string","null"],"description":"Full URL for the next page, or `null` on the last page."},"prevPageUrl":{"type":["string","null"],"description":"Full URL for the previous page, or `null` when already at the head."}},"required":["children"]},"FlowJobLogEntry":{"type":"object","description":"One entry in a paginated flow-job log listing. Each entry represents a single record processed by a\nsingle step (export or import) within a flow run.","properties":{"startedAt":{"type":"string","format":"date-time","description":"When this step began processing the record."},"recordId":{"type":"string","description":"Opaque per-record identifier."},"groupId":{"type":"string","description":"Opaque batch identifier — records processed in the same page/batch share a groupId."},"traceKey":{"type":"string","description":"Trace identifier that pairs an export entry with the import entries that processed its output."},"_expOrImpId":{"type":"string","format":"objectId","description":"Id of the export or import step that produced this entry."},"status":{"type":"string","description":"Outcome of this step for this record.","enum":["success","error","ignore"]},"timeTaken":{"type":"integer","description":"Milliseconds spent processing this record at this step."}},"required":["recordId","groupId","_expOrImpId","status"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}},"404-not-found":{"description":"Not found. The requested resource does not exist or is not visible to the caller.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/flows/{_id}/jobs/{_jobId}/{_stepId}/logs/{recordId}/children":{"get":{"operationId":"listFlowJobStepLogChildren","tags":["Flows"],"summary":"List child log records for a parent record","description":"Returns one page of child log records for a specific parent record within a flow-run step.\nChild records represent sub-operations (e.g. individual batch items, lookup expansions, or\nretry attempts) spawned by the parent record during step processing.\n\nPagination is body-driven: follow `nextPageUrl` / `prevPageUrl` until they are `null`.\nPagination cursors use `offset` (numeric) and `next`/`prev` (ISO timestamp) parameters\nembedded in the URL.\n\nAI guidance:\n- Use this to drill into fan-out or batch-split scenarios where one parent record produces\n  multiple child operations at a step.\n- Filter by `status` to isolate failures within a batch.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"_jobId","in":"path","required":true,"description":"Flow-run job id.","schema":{"type":"string","format":"objectId"}},{"name":"_stepId","in":"path","required":true,"description":"Export or import step id within the flow.","schema":{"type":"string","format":"objectId"}},{"name":"recordId","in":"path","required":true,"description":"Parent record id whose children to retrieve.","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"Filter child records by outcome.","schema":{"type":"string","enum":["success","error","ignore"]}},{"name":"pageSize","in":"query","required":false,"description":"Number of child records per page. Must be between 1 and 1000.","schema":{"type":"integer","minimum":1,"maximum":1000}}],"responses":{"200":{"description":"One page of child log records.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowJobLogChildrenResponse"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Get request/response logs for a flow test-run step

> Returns the outbound HTTP request/response log pairs captured during a\
> specific step of a flow test run. Only steps that issued outbound HTTP\
> calls (exports, imports, lookups) produce entries — routers, filters, and\
> other in-process stages return \*\*404 \`req\_res\_logs\_not\_found\`\*\* by\
> design.\
> \
> The \`runId\` comes from the \`POST /v1/flows/{\_id}/test/run\` response (not\
> from a normal flow run Job record — test runs and regular runs are\
> separate histories). \`{\_stepId}\` is the export or import id of the step\
> you want logs for; find the id in the test-run metadata's \`stages\[]\`.\
> \
> \*\*Endpoint template applies across three resource families.\*\* The same\
> path shape also exists for Tools (\`/v1/tools/{\_id}/test/run/.../logs/requestAndResponse\`)\
> and builder-mode APIs (\`/v1/apis/{\_id}/test/run/.../logs/requestAndResponse\`).\
> This spec documents the flow variant — the request/response shape is the\
> same across all three.\
> \
> AI guidance:\
> \- Response entries may carry \*\*base64-encoded JSON\*\* in \`request.body\`\
> &#x20; and \`response.body\` fields — the Celigo CLI transparently decodes\
> &#x20; these client-side before formatting. Callers should try\
> &#x20; base64-decoding string bodies before treating them as opaque.\
> \- 404 here is not always an error — it's the signal that a non-HTTP step\
> &#x20; was selected. Cross-check against the test-run metadata's stage list\
> &#x20; before surfacing a failure to the user.\
> \- \`runId\` expires with the test run — runs are short-lived ephemeral\
> &#x20; state, not persisted like flow-run Jobs. Capture the logs soon after\
> &#x20; the test run completes.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}},"schemas":{"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}}},"paths":{"/v1/flows/{_id}/test/run/{runId}/{_stepId}/logs/requestAndResponse":{"get":{"operationId":"getFlowTestRunStepLogs","tags":["Flows"],"summary":"Get request/response logs for a flow test-run step","description":"Returns the outbound HTTP request/response log pairs captured during a\nspecific step of a flow test run. Only steps that issued outbound HTTP\ncalls (exports, imports, lookups) produce entries — routers, filters, and\nother in-process stages return **404 `req_res_logs_not_found`** by\ndesign.\n\nThe `runId` comes from the `POST /v1/flows/{_id}/test/run` response (not\nfrom a normal flow run Job record — test runs and regular runs are\nseparate histories). `{_stepId}` is the export or import id of the step\nyou want logs for; find the id in the test-run metadata's `stages[]`.\n\n**Endpoint template applies across three resource families.** The same\npath shape also exists for Tools (`/v1/tools/{_id}/test/run/.../logs/requestAndResponse`)\nand builder-mode APIs (`/v1/apis/{_id}/test/run/.../logs/requestAndResponse`).\nThis spec documents the flow variant — the request/response shape is the\nsame across all three.\n\nAI guidance:\n- Response entries may carry **base64-encoded JSON** in `request.body`\n  and `response.body` fields — the Celigo CLI transparently decodes\n  these client-side before formatting. Callers should try\n  base64-decoding string bodies before treating them as opaque.\n- 404 here is not always an error — it's the signal that a non-HTTP step\n  was selected. Cross-check against the test-run metadata's stage list\n  before surfacing a failure to the user.\n- `runId` expires with the test run — runs are short-lived ephemeral\n  state, not persisted like flow-run Jobs. Capture the logs soon after\n  the test run completes.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow id.","schema":{"type":"string","format":"objectId"}},{"name":"runId","in":"path","required":true,"description":"Test run id from the `POST /v1/flows/{_id}/test/run` response.\nDistinct from flow-run Job ids.","schema":{"type":"string"}},{"name":"_stepId","in":"path","required":true,"description":"Export or import id of the step whose logs you want. Non-HTTP\nstages (routers, filters) 404 with `req_res_logs_not_found`.","schema":{"type":"string","format":"objectId"}}],"responses":{"200":{"description":"Array of request/response log pairs captured during the step.\n`request.body` / `response.body` may be base64-encoded JSON.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","description":"One request/response pair captured by the test engine.","properties":{"request":{"type":"object","description":"Outbound HTTP request envelope.","properties":{"method":{"type":"string","description":"HTTP method (e.g. `GET`, `POST`)."},"url":{"type":"string","description":"Fully-resolved request URL."},"headers":{"type":"object","description":"Request headers; sensitive values redacted server-side.","additionalProperties":true},"body":{"description":"Request body. Often **base64-encoded JSON** — decode\nbefore parsing. Empty for bodyless methods.","type":["string","null"]}}},"response":{"type":"object","description":"Remote response envelope.","properties":{"statusCode":{"type":"integer","description":"HTTP status code returned by the remote."},"headers":{"type":"object","description":"Response headers.","additionalProperties":true},"body":{"description":"Response body. Often **base64-encoded JSON** —\ndecode before parsing.","type":["string","null"]}}}}}}}}},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"description":"Either the run/step id didn't resolve, or the step produced no\nrequest/response logs (non-HTTP stage — router, filter, etc.).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
```

## Cancel a flow execution group

> Cancels all remaining jobs in a flow execution group. Execution groups are created when multiple\
> flows are triggered together (e.g. via integration-level run or chained flows) and share a common\
> group identifier.\
> \
> The response varies depending on whether there were jobs left to cancel:\
> \- \*\*200\*\* with \`{"message": "No more jobs to cancel"}\` when no in-progress jobs remain.\
> \- \*\*204\*\* with no body when cancellation was successfully requested.\
> \
> This endpoint is not scoped to a specific flow — the \`\_id\` parameter is the execution group id,\
> not a flow id. Any string is accepted as the id (the server does not validate that the group\
> exists before responding).\
> \
> AI guidance:\
> \- Use this when you need to stop an entire batch of related flow runs, not just one flow.\
> \- Since the server accepts any string as the id without validation, a 200/204 response does not\
> &#x20; confirm the group existed — verify via job-listing endpoints if confirmation is needed.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}}},"paths":{"/v1/flowExecutionGroups/{_id}/cancel":{"put":{"operationId":"cancelFlowExecutionGroup","tags":["Flows"],"summary":"Cancel a flow execution group","description":"Cancels all remaining jobs in a flow execution group. Execution groups are created when multiple\nflows are triggered together (e.g. via integration-level run or chained flows) and share a common\ngroup identifier.\n\nThe response varies depending on whether there were jobs left to cancel:\n- **200** with `{\"message\": \"No more jobs to cancel\"}` when no in-progress jobs remain.\n- **204** with no body when cancellation was successfully requested.\n\nThis endpoint is not scoped to a specific flow — the `_id` parameter is the execution group id,\nnot a flow id. Any string is accepted as the id (the server does not validate that the group\nexists before responding).\n\nAI guidance:\n- Use this when you need to stop an entire batch of related flow runs, not just one flow.\n- Since the server accepts any string as the id without validation, a 200/204 response does not\n  confirm the group existed — verify via job-listing endpoints if confirmation is needed.","parameters":[{"name":"_id","in":"path","required":true,"description":"Flow execution group id.","schema":{"type":"string"}}],"responses":{"200":{"description":"No more jobs to cancel in the group.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Status message."}},"required":["message"]}}}},"204":{"description":"Cancellation requested for remaining jobs in the group. No response body."},"401":{"$ref":"#/components/responses/401-unauthorized"}}}}}}
```

## Get static filter enum metadata for errors

> Returns the static enumeration values used to filter errors across the platform. The response\
> is not scoped to the authenticated user — every caller receives the same set of filter\
> dimensions and allowed values.\
> \
> Currently returns two filter dimensions:\
> \- \*\*source\*\* (24 values): \`internal\`, \`application\`, \`connection\`, \`resource\`,\
> &#x20; \`transformation\`, \`output\_filter\`, \`input\_filter\`, \`import\_filter\`, \`lookup\`, \`mapping\`,\
> &#x20; \`response\_mapping\`, \`pre\_save\_page\_hook\`, \`pre\_parse\_hook\`, \`pre\_map\_hook\`, \`post\_map\_hook\`,\
> &#x20; \`post\_submit\_hook\`, \`post\_response\_map\_hook\`, \`post\_aggregate\_hook\`, \`pre\_send\_hook\_ss\`,\
> &#x20; \`pre\_map\_hook\_ss\`, \`post\_map\_hook\_ss\`, \`post\_submit\_hook\_ss\`, \`tool\_input\`, \`tool\_output\`.\
> \- \*\*classification\*\* (10 values): \`connection\`, \`duplicate\`, \`governance\`, \`intermittent\`,\
> &#x20; \`missing\`, \`parse\`, \`value\`, \`rate\_limit\`, \`too\_large\`, \`none\`.\
> \
> AI guidance:\
> \- Use this to populate filter dropdowns or validate filter values before passing them to error\
> &#x20; listing endpoints.\
> \- The values are static — cache them aggressively. They don't change between calls or users.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"ErrorsFilterMetadataResponse":{"type":"object","description":"Static enumeration metadata for error filters. Returned by `GET /v1/errors/filterMetadata`.\nValues are not scoped to the authenticated user — the same set is returned for every caller.","properties":{"filters":{"type":"array","description":"Available filter dimensions with their allowed enum values.","items":{"type":"object","properties":{"name":{"type":"string","description":"Filter field name (e.g. `source`, `classification`)."},"enums":{"type":"array","description":"Allowed values for this filter dimension.","items":{"type":"string"}}},"required":["name","enums"]}}},"required":["filters"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}}},"paths":{"/v1/errors/filterMetadata":{"get":{"operationId":"getErrorsFilterMetadata","tags":["Flows"],"summary":"Get static filter enum metadata for errors","description":"Returns the static enumeration values used to filter errors across the platform. The response\nis not scoped to the authenticated user — every caller receives the same set of filter\ndimensions and allowed values.\n\nCurrently returns two filter dimensions:\n- **source** (24 values): `internal`, `application`, `connection`, `resource`,\n  `transformation`, `output_filter`, `input_filter`, `import_filter`, `lookup`, `mapping`,\n  `response_mapping`, `pre_save_page_hook`, `pre_parse_hook`, `pre_map_hook`, `post_map_hook`,\n  `post_submit_hook`, `post_response_map_hook`, `post_aggregate_hook`, `pre_send_hook_ss`,\n  `pre_map_hook_ss`, `post_map_hook_ss`, `post_submit_hook_ss`, `tool_input`, `tool_output`.\n- **classification** (10 values): `connection`, `duplicate`, `governance`, `intermittent`,\n  `missing`, `parse`, `value`, `rate_limit`, `too_large`, `none`.\n\nAI guidance:\n- Use this to populate filter dropdowns or validate filter values before passing them to error\n  listing endpoints.\n- The values are static — cache them aggressively. They don't change between calls or users.","parameters":[],"responses":{"200":{"description":"Static filter metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorsFilterMetadataResponse"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"}}}}}}
```

## Preview the output of a flow's page processor

> Runs a flow's page generators and page processors through the preview\
> pipeline and returns the sampled output at a specific page-processor\
> node. Same engine as \`POST /v1/exports/preview\`, but scoped to a\
> pageProcessor inside a flow rather than a standalone export.\
> \
> Body carries the flow shape plus resolved maps of page-generator and\
> page-processor docs keyed by \`\_id\`. The server uses those maps as the\
> source of truth for the preview — it does not read the persisted flow\
> doc, so callers can pass modified versions to "what-if" iterate.\
> \
> AI guidance:\
> \- Body field is \`flow\` (not \`flowDoc\` — the API's "flowDoc is required"\
> &#x20; error message is stale: the accepted field name is \`flow\`). Passing\
> &#x20; neither triggers 400 \`missing\_required\_field\` referencing \`flowDoc\`.\
> \- Every entry referenced by \`flow\.pageGenerators\[].\_exportId\` must exist\
> &#x20; in \`pageGeneratorMap\` keyed by that id, wrapped as \`{doc, options}\`;\
> &#x20; same shape for \`pageProcessorMap\`. Missing entries return 400\
> &#x20; \`missing\_pageGenerator\_doc\` (with the \`\_id\` in the message).\
> \- \`includeStages: true\` populates the stage-by-stage diagnostic array on\
> &#x20; the response (recommended). Without it, callers only get the\
> &#x20; final-stage data.\
> \- \`\_selectedPageGeneratorId\` narrows which generator drives the preview\
> &#x20; when the flow has multiple; defaults to the first \`pageGenerators\[0]\`.\
> \- Same POST-safe semantics as \`/v1/exports/preview\` — no side effects,\
> &#x20; no Job created, no flow state changes.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"PageProcessorsPreviewRequest":{"type":"object","description":"Flow-page-processor preview request. Carries the flow shape plus\nside-loaded maps of page-generator and page-processor docs so the\npreview engine can run without reading the persisted flow doc.","properties":{"flow":{"type":"object","description":"Flow document. Must at minimum carry `pageGenerators[]` and\n`pageProcessors[]` with `_exportId` / `_importId` references that\nmatch keys in the side-loaded maps. Full flow doc shape mirrors\n`POST /v1/flows` body. Accepted under key `flow` despite the\nserver's stale `flowDoc` error message.","additionalProperties":true},"flowDoc":{"type":"object","description":"Alias for `flow` — the server appears to accept either key.\nPrefer `flow`.","additionalProperties":true},"_pageProcessorId":{"type":"string","format":"objectId","description":"The pageProcessor resource id to preview. Must be present as a key\nin `pageProcessorMap`."},"_selectedPageGeneratorId":{"type":"string","format":"objectId","description":"Page generator to drive the preview when the flow has multiple.\nDefaults to `flow.pageGenerators[0]._exportId`."},"pageGeneratorMap":{"type":"object","description":"Map of page-generator `_id` → `{doc, options}`. `doc` is the full\nexport doc for that generator; `options` is a preview-time hints\nobject (typically `{}` or `{preview: true}`).","additionalProperties":{"type":"object","properties":{"doc":{"type":"object","additionalProperties":true},"options":{"type":"object","additionalProperties":true}}}},"pageProcessorMap":{"type":"object","description":"Map of page-processor `_id` → `{doc, options}`. Shape matches\n`pageGeneratorMap`; `options.preview: true` is typically set on the\nentry matching `_pageProcessorId`.","additionalProperties":{"type":"object","properties":{"doc":{"type":"object","additionalProperties":true},"options":{"type":"object","additionalProperties":true}}}},"includeStages":{"type":"boolean","description":"Include stage-by-stage diagnostics (`stages[]`) in the response.\nRecommended — without it the response loses the per-stage data and\nerror breakdown."}},"required":["_pageProcessorId","pageGeneratorMap","pageProcessorMap"]},"ExportPreviewResponse":{"type":"object","description":"Envelope returned by `POST /v1/exports/preview` (and the scoped\n`/v1/integrations/{_integrationId}/flows/{_flowId}/exports/preview`\nvariant). Carries per-stage diagnostics alongside the sampled records.","properties":{"data":{"type":"array","description":"Final sampled records produced by the preview — the output of the last\nstage. Identical in practice to the last `stages[].data` entry, exposed\nhere as a convenience for callers that only care about the end result.","items":{}},"dataURIs":{"type":"array","description":"URIs for any files produced by the preview (e.g. file-based exports\nwriting to cloud storage). Empty for non-file adaptors.","items":{"type":"string"}},"dataRecordTraceKeys":{"type":"array","description":"Trace keys for the records in this preview — one per record,\ncorrelating stage outputs to their source record.","items":{"type":"string"}},"stages":{"type":"array","description":"Ordered list of pipeline stages the preview traversed. Stage names\ninclude `preSavePageHook`, `apiCall`, `transform`, `postResponseHook`,\netc. Each stage carries its `data[]` output and any `errors[]`\nraised at that stage.","items":{"type":"object","description":"One pipeline stage's diagnostic and output envelope.","properties":{"name":{"type":"string","description":"Stage identifier (e.g. `preSavePageHook`, `apiCall`)."},"data":{"description":"Stage output. Shape varies — apiCall stages produce the raw\nrecords; hook stages may produce transformed records.","oneOf":[{"title":"Array","type":"array","items":{}},{"title":"Object","type":"object","additionalProperties":true},{"title":"Null","type":"null"}]},"errors":{"type":["array","null"],"description":"Errors raised at this stage, or `null` when clean.","items":{"type":"object","additionalProperties":true}}}}},"errors":{"type":"array","description":"Top-level error aggregate — typically mirrors the first non-null\n`stages[].errors[]` entry. Often omitted entirely when the preview\nran clean; callers should treat `undefined` and `[]` as equivalent.","items":{"type":"object","additionalProperties":true}},"traceKeysDuplicate":{"type":"array","description":"Trace keys that collided during the preview — a diagnostic for\ntrace-key generation; rarely non-empty in practice.","items":{"type":"string"}}}},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}}},"paths":{"/v1/pageProcessors/preview":{"post":{"operationId":"previewPageProcessor","tags":["Flows"],"summary":"Preview the output of a flow's page processor","description":"Runs a flow's page generators and page processors through the preview\npipeline and returns the sampled output at a specific page-processor\nnode. Same engine as `POST /v1/exports/preview`, but scoped to a\npageProcessor inside a flow rather than a standalone export.\n\nBody carries the flow shape plus resolved maps of page-generator and\npage-processor docs keyed by `_id`. The server uses those maps as the\nsource of truth for the preview — it does not read the persisted flow\ndoc, so callers can pass modified versions to \"what-if\" iterate.\n\nAI guidance:\n- Body field is `flow` (not `flowDoc` — the API's \"flowDoc is required\"\n  error message is stale: the accepted field name is `flow`). Passing\n  neither triggers 400 `missing_required_field` referencing `flowDoc`.\n- Every entry referenced by `flow.pageGenerators[]._exportId` must exist\n  in `pageGeneratorMap` keyed by that id, wrapped as `{doc, options}`;\n  same shape for `pageProcessorMap`. Missing entries return 400\n  `missing_pageGenerator_doc` (with the `_id` in the message).\n- `includeStages: true` populates the stage-by-stage diagnostic array on\n  the response (recommended). Without it, callers only get the\n  final-stage data.\n- `_selectedPageGeneratorId` narrows which generator drives the preview\n  when the flow has multiple; defaults to the first `pageGenerators[0]`.\n- Same POST-safe semantics as `/v1/exports/preview` — no side effects,\n  no Job created, no flow state changes.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageProcessorsPreviewRequest"}}}},"responses":{"200":{"description":"Preview envelope. Mirrors `ExportPreviewResponse` — `stages[]` carries\nthe stage-by-stage output + errors, and the top-level `errors[]`\naggregates any configuration failures surfaced during the run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExportPreviewResponse"}}}},"400":{"description":"Request structural errors. Common codes:\n- `missing_required_field` — `flow`/`flowDoc` (note: error message\n  references `flowDoc` even though `flow` is the accepted key name).\n- `missing_pageGenerator_doc` — an `_id` referenced in\n  `flow.pageGenerators[]` has no entry in `pageGeneratorMap`.\n- `missing_pageProcessor_doc` — mirror of the above for processors.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"}}}}}}
```

## List dependencies of a flow

> Returns the set of resources that depend on the specified resource.\
> The response is an object whose keys are dependent-resource types\
> (e.g. \`flows\`, \`imports\`) and whose values are arrays of dependency\
> entries.\
> \
> AI guidance:\
> \- An empty object \`{}\` means no other resources depend on the target.\
> &#x20; This is also returned for a well-formatted but nonexistent id.

```json
{"openapi":"3.1.0","info":{"title":"Flows","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"DependencyResponse":{"type":"object","description":"Map of dependent-resource types to arrays of dependency entries.\nKeys are plural resource type strings (e.g. `flows`, `imports`,\n`connections`). An empty object `{}` means no dependents.\n","additionalProperties":{"type":"array","items":{"$ref":"#/components/schemas/DependencyEntry"}}},"DependencyEntry":{"type":"object","description":"A single resource that depends on the queried resource.","properties":{"id":{"type":"string","description":"Unique identifier of the dependent resource."},"name":{"type":"string","description":"Display name of the dependent resource."},"paths":{"type":"array","description":"JSON-path-style pointers within the dependent resource's document\nthat reference the target resource.\n","items":{"type":"string"}},"accessLevel":{"type":"string","description":"The caller's access level on the dependent resource."},"dependencyIds":{"type":"object","description":"Map of resource types to arrays of ids that this dependent\nresource references on the target. Keys are singular or plural\nresource type strings; values are arrays of id strings.\n","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["id","name","paths","accessLevel","dependencyIds"]}},"responses":{"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}}},"paths":{"/v1/flows/{_id}/dependencies":{"get":{"operationId":"listFlowDependencies","tags":["Flows"],"summary":"List dependencies of a flow","description":"Returns the set of resources that depend on the specified resource.\nThe response is an object whose keys are dependent-resource types\n(e.g. `flows`, `imports`) and whose values are arrays of dependency\nentries.\n\nAI guidance:\n- An empty object `{}` means no other resources depend on the target.\n  This is also returned for a well-formatted but nonexistent id.","parameters":[{"name":"_id","in":"path","required":true,"description":"Resource ID.","schema":{"type":"string","format":"objectId"}}],"responses":{"200":{"description":"Dependency map. Keys are resource-type strings; values are arrays\nof dependency entries. Returns `{}` when no dependents exist.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DependencyResponse"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"}}}}}}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developer.celigo.com/api/api-reference/flows.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
