> For the complete documentation index, see [llms.txt](https://developer.celigo.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.celigo.com/api/api-reference/flows.md).

# Flows

Flows orchestrate how data moves between systems. A flow chains one or more page generators (exports that produce records) into a pipeline of page processors (lookups and imports), with optional routers for conditional branching. Flows run on a cron schedule, on demand, or in response to real-time events, and expose endpoints for running, monitoring, and managing per-step errors.

## The Flow object

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"components":{"schemas":{"Flow":{"type":"object","required":["_id","name","disabled","logging","createdAt","lastModified"],"description":"Flow object as returned by the API.","allOf":[{"$ref":"#/components/schemas/FlowBase"},{"$ref":"#/components/schemas/ResourceResponse"},{"type":"object","properties":{"lastExecutedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp of the flow's most recent execution. Absent until the flow has run at least once."},"resolvedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow's open errors were last resolved."},"free":{"type":"boolean","readOnly":true,"description":"When true, the flow is free to run and does not require a paid subscription."},"_templateId":{"type":"string","format":"objectId","readOnly":true,"description":"Template this flow was created from."},"_sourceId":{"type":"string","format":"objectId","readOnly":true,"description":"Source resource this flow was cloned or installed from."}}}]},"FlowBase":{"type":"object","description":"Writable flow fields shared by the request and response schemas.\n\nUse `pageProcessors` for simple linear flows or `routers` for conditional branching — never\ninclude both. The `schedule` field uses Celigo's 6-field cron format (not standard 5-field),\nwhere hours must be explicit comma-separated lists.","properties":{"name":{"type":"string","maxLength":150,"description":"Display name for the flow."},"description":{"type":"string","maxLength":5120,"description":"Free-text description of the flow's purpose."},"_integrationId":{"type":["string","null"],"format":"objectId","description":"Integration this flow belongs to."},"schedule":{"type":["string","null"],"description":"Celigo 6-field cron expression: `? minute hour day-of-month month day-of-week`.\nHours must be explicit comma-separated lists (not `*/4` or `*`). Leave empty for\nevent-driven or webhook-triggered flows."},"timezone":{"type":["string","null"],"description":"IANA timezone for the schedule (e.g. `America/New_York`). Defaults to UTC."},"disabled":{"type":"boolean","description":"When true, scheduled executions are suspended and the flow cannot be triggered.\nRunning jobs are allowed to complete.","default":false},"pageGenerators":{"type":"array","description":"Data sources (exports) that produce pages of records for the flow. Mutually exclusive with\ntop-level `pageProcessors` when `routers` is used.","items":{"$ref":"#/components/schemas/PageGenerator"}},"pageProcessors":{"type":"array","description":"Sequential processing steps (imports, lookups, routers). Mutually exclusive with `routers` —\nuse one or the other, not both.","items":{"$ref":"#/components/schemas/PageProcessor"}},"routers":{"type":"array","description":"Routing configurations that direct records to conditional branches. Mutually exclusive with\ntop-level `pageProcessors` — use one or the other, not both.","items":{"$ref":"#/components/schemas/Router"}},"_runNextFlowIds":{"type":"array","description":"Flow IDs to trigger after this flow completes successfully.","items":{"type":"string","format":"objectId"}},"_runNextExportIds":{"type":"array","description":"Specific exports in other flows to trigger after completion.","items":{"type":"object","properties":{"_flowId":{"type":"string","format":"objectId","description":"Flow containing the export to trigger."},"_exportId":{"type":"string","format":"objectId","description":"Export to execute."}}}},"externalId":{"type":["string","null"],"description":"External identifier for correlating the flow with a record in another system."},"wizardState":{"type":"string","enum":["step2","step3","done"],"description":"Tracks how far the user has progressed through the flow setup wizard in the UI."},"settings":{"type":"object","description":"Custom key-value settings passed to hooks and scripts at runtime.","additionalProperties":true},"_connectorId":{"type":"string","format":"objectId","description":"Connector template this flow was created from."},"runPageGeneratorsInParallel":{"type":"boolean","description":"When true, all page generators start simultaneously instead of sequentially."},"autoResolveMatchingTraceKeys":{"type":"boolean","description":"When true, new errors with trace keys matching existing open errors are auto-resolved."},"isAbstract":{"type":"boolean","description":"Marks this as an abstract (multi-instance) flow — a reusable template that cannot be\nexecuted directly. Instance flows reference it via `_abstractFlowId` and provide `overrides`.\n\nConstraints: top-level `pageProcessors` are not allowed (use `routers`), cannot reference\nanother abstract flow, cannot be a \"run next\" target, and cannot be unset while instances exist."},"_abstractFlowId":{"type":"string","format":"objectId","description":"Abstract flow this instance inherits from. Immutable once set. The instance inherits\nthe flow graph and uses `overrides` to customize connections, schedules, and hooks."},"overrides":{"$ref":"#/components/schemas/Overrides"},"overridesHelper":{"$ref":"#/components/schemas/OverridesHelper"},"hidden":{"type":"boolean","description":"When true, the flow is hidden from standard UI views but remains executable via API."},"_flowGroupingId":{"type":["string","null"],"format":"objectId","description":"Flow grouping for organizing related flows in the UI. References an entry in the\nintegration's `flowGroupings` array (not a standalone collection); invalid ids are\nsilently dropped by the server."},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Coordinates delta timing so this flow's checkpoint stays behind the referenced flow.\nUsed for parent-child data relationships where the parent must sync first."},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Like `_keepDeltaBehindFlowId` but targets a specific export within a flow."},"aiDescription":{"$ref":"#/components/schemas/AIDescription"},"aliases":{"type":"array","description":"Named aliases that map to specific resources within the flow.","items":{"type":"object","properties":{"alias":{"type":"string","description":"Alias name."},"_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":"When true, this flow is in draft mode and not yet published."},"draftExpiresAt":{"type":"string","format":"date-time","description":"Timestamp when the draft version expires."},"logging":{"type":"object","description":"Flow-level logging configuration.","properties":{"mode":{"type":"string","description":"Logging verbosity level.","enum":["accountLevel","basic","detailed"]},"debugUntil":{"type":"string","format":"date-time","description":"Temporary debug-level logging until this timestamp (max 1 hour from now)."}}},"numInstances":{"type":"integer","description":"Number of instance flows derived from this abstract flow.","readOnly":true},"preSave":{"type":"object","description":"Pre-save hook that runs a script before persisting flow changes.","properties":{"function":{"type":"string","description":"Function name to invoke."},"_scriptId":{"type":"string","format":"objectId","description":"Script containing the pre-save function."}}},"settingsForm":{"type":"object","description":"Form definition for collecting flow-level settings from users in the UI.","additionalProperties":true}}},"PageGenerator":{"type":"object","description":"A data source that produces pages of records for the flow. Page generators are the\nentry points of a flow; each references an export, can carry its own schedule, and\nmultiple generators can run in parallel when the flow enables it.","required":["_exportId"],"properties":{"_exportId":{"type":"string","format":"objectId","description":"Export that retrieves data from the source system. The server rejects page\ngenerator entries without a valid export reference."},"schedule":{"type":"string","description":"Cron expression for this specific generator, overriding the flow's main schedule.\nWhen omitted, the generator inherits the flow's schedule."},"skipRetries":{"type":"boolean","description":"When true, failed records from this generator are not retried — errors are logged\nand the flow continues. When false, failed records are retried per platform policy."},"setupInProgress":{"type":"boolean","description":"When true, the generator's configuration is still being set up in the UI and the step is not yet runnable."},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Coordinates delta timing so this generator's checkpoint stays behind the referenced\nflow, preventing child records from being processed before their parents."},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Like `_keepDeltaBehindFlowId` but targets a specific export's delta timestamp."},"__startDateHelper":{"type":"string","description":"Internal helper field for managing scheduled start dates."}}},"PageProcessor":{"type":"object","description":"A processing step that operates on pages of records within a flow. Processors are\neither lookups (`type: export`) that enrich records or imports (`type: import`) that\nwrite records to a destination, and execute sequentially unless routed into branches.","required":["type"],"properties":{"type":{"type":"string","description":"Selects whether this step runs a lookup export or an import, and which reference field applies.","enum":["export","import"]},"_exportId":{"type":"string","format":"objectId","description":"Lookup export that enriches incoming records. Required when `type` is `export`;\nthe referenced export must be configured as a lookup (`isLookup: true`)."},"_importId":{"type":"string","format":"objectId","description":"Import that writes records to the destination system. Required when `type` is `import`."},"proceedOnFailure":{"type":"boolean","description":"When true, records that fail in this processor continue to subsequent steps and the\nerror is logged. When false, failed records stop at this step."},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"hooks":{"type":"object","description":"Custom code hooks extending this processor's behavior.","properties":{"postResponseMap":{"type":"object","description":"Hook that runs after the step's response mapping completes.","properties":{"function":{"type":"string","description":"Function to invoke within the referenced script."},"_scriptId":{"type":"string","format":"objectId","description":"Script containing the hook function named in `function`."}}}}},"setupInProgress":{"type":"boolean","description":"When true, the processor's configuration is still being set up in the UI and the step is not yet runnable."}},"if":{"properties":{"type":{"const":"export"}},"required":["type"]},"then":{"required":["_exportId"]},"else":{"if":{"properties":{"type":{"const":"import"}},"required":["type"]},"then":{"required":["_importId"]}}},"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":"When true, marks this entry as an internal identifier."}}}},"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":"When true, marks this entry as an internal identifier."}}}},"_id":{"type":"boolean","description":"When true, marks this entry as an internal identifier."}}}},"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.","enum":["first_matching_branch","all_matching_branches"],"default":"first_matching_branch"},"routeRecordsUsing":{"type":"string","description":"Method used to evaluate routing criteria.","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","description":"Version of the filter expression format used by the rules; currently only \"1\" is supported."},"rules":{"type":"object","additionalProperties":true,"description":"Filter expression defining the matching criteria, in prefix notation — the operator first, followed by its operands, which may be nested expressions."}}},"groupByFields":{"type":"array","description":"Override grouping fields","items":{"type":"string"}},"test":{"type":"object","description":"Override test mode settings","properties":{"limit":{"type":"integer","description":"Overrides the test-mode record cap on the abstract flow's export — the total number of records a test run processes."}}},"delta":{"type":"object","description":"Override delta configuration","properties":{"dateField":{"type":"string","description":"Overrides the delta date field on the abstract flow's export — the record timestamp field(s) compared against the last successful run time to identify changed records. Accepts a single field or multiple comma-separated fields."},"dateFormat":{"type":"string","description":"Overrides the moment.js format string applied to the delta cutoff timestamp; ISO 8601 is used when unset."},"startDate":{"type":"string","description":"Overrides the fixed start timestamp used for the delta window on the abstract flow's export, in place of the last successful run time."},"lagOffset":{"type":"integer","description":"Overrides the buffer in milliseconds subtracted from the last successful run timestamp, creating an overlapping window that catches late-propagating records."},"endDateField":{"type":"string","description":"Overrides the record timestamp field used as the upper bound of the delta window on the abstract flow's export."}}},"once":{"type":"object","description":"Override once export settings","properties":{"booleanField":{"type":"string","description":"Overrides the once-mode tracking field on the abstract flow's export — the boolean field in the source system that is false for unprocessed records and set to true after successful processing."}}},"valueDelta":{"type":"object","description":"Override value delta settings","properties":{"exportedField":{"type":"string","description":"Overrides the field that tracks the last exported value on the abstract flow's export."},"pendingField":{"type":"string","description":"Overrides the field that tracks the pending (not yet exported) value on the abstract flow's export."}}},"webhook":{"type":"object","description":"Override webhook configuration","properties":{"token_crypt":{"type":"string","description":"Encrypted form of the webhook verification token, stored at rest."},"token_salt":{"type":"string","description":"Salt used to encrypt the corresponding webhook token."},"path":{"type":"string","description":"Overrides the location of the verification token on the abstract flow's webhook export — a JSON path into the request body or a query parameter name."},"key_crypt":{"type":"string","description":"Encrypted form of the webhook HMAC or public key, stored at rest."},"key_salt":{"type":"string","description":"Salt used to encrypt the corresponding webhook key."},"header":{"type":"string","description":"Overrides the name of the request header that carries the HMAC signature on the abstract flow's webhook export."},"username":{"type":"string","description":"Overrides the username used for basic-auth webhook verification on the abstract flow's export."},"password_crypt":{"type":"string","description":"Encrypted form of the basic-auth webhook password, stored at rest."},"password_salt":{"type":"string","description":"Salt used to encrypt the corresponding webhook password."},"successStatusCode":{"type":"integer","description":"Overrides the HTTP status code returned to the webhook caller after successful processing."},"successBody":{"type":"string","description":"Overrides the response body returned to the webhook caller after successful processing; ignored when the status code is 204."},"successMediaType":{"type":"string","description":"Overrides the Content-Type of successful webhook responses; must match the format of the success body."}}},"distributed":{"type":"object","description":"Override distributed processing settings","properties":{"bearerToken_crypt":{"type":"string","description":"Encrypted form of the distributed export's bearer token, stored at rest."},"bearerToken_salt":{"type":"string","description":"Salt used to encrypt the corresponding bearer token."}}},"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","description":"Overrides the ID lock template on the abstract flow's import — a handlebars template that generates a lock key so records resolving to the same key are not submitted concurrently."},"dataURITemplate":{"type":"string","description":"Overrides the data URI template on the abstract flow's import — a handlebars template that builds a link back to each record in the destination application's UI for error tracking."},"pathToMany":{"type":"string","description":"Overrides the one-to-many path on the abstract flow's import — the JSON path to child records within each parent record."},"blobKeyPath":{"type":"string","description":"Overrides the blob key path on the abstract flow's import — the path in the input record that holds the blob key identifying file content to import."},"filter":{"type":"object","additionalProperties":true,"description":"Overrides the filter on the abstract flow's import, which selects which incoming records are sent to the destination system."},"traceKeyTemplate":{"type":"string","description":"Overrides the trace key template on the abstract flow's import — a handlebars template controlling how each record's unique trace key is generated."},"parsers":{"type":"array","items":{"type":"object"},"description":"Overrides the parser configurations on the abstract flow's import."},"hooks":{"type":"object","additionalProperties":true,"description":"Overrides the hook configurations on the abstract flow's import — custom JavaScript hooks that run at fixed points in the import lifecycle."},"responseTransform":{"type":"object","additionalProperties":true,"description":"Overrides the response transform on the abstract flow's import, which reshapes the destination system's response after records are imported."},"mapping":{"type":"object","additionalProperties":true,"description":"Overrides the Mapper 1.0 mapping configuration on the abstract flow's import."},"mappings":{"type":"array","items":{"type":"object"},"description":"Overrides the Mapper 2.0 field mappings on the abstract flow's import, which transform incoming records into the destination system's field structure."},"lookups":{"type":"array","items":{"type":"object"},"description":"Overrides the lookup definitions on the abstract flow's import, referenced by its field mappings."},"settingsForm":{"type":"object","additionalProperties":true,"description":"Overrides the settings form definition on the abstract flow's import, which prompts users for values stored in `settings`."},"preSave":{"type":"object","additionalProperties":true,"description":"Overrides the preSave hook on the abstract flow's import — a JavaScript hook that executes before the resource is saved."},"settings":{"type":"object","additionalProperties":true,"description":"Overrides the custom settings on the abstract flow's import, accessible to hooks, filters, mappings, and handlebars templates at runtime."}}}},"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","description":"Reference to the script resource containing the routing logic used in place of the abstract router's script."},"function":{"type":"string","description":"Function name within the script that returns the branch name for each record."}}},"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":"Overrides the branch's display name within the router."},"description":{"type":"string","description":"Overrides the branch's description explaining its purpose and criteria."},"inputFilter":{"type":"object","description":"Overrides the branch's input filter — the criteria that determine which records are routed to this branch.","properties":{"version":{"type":"string","description":"Version of the filter expression format used by the rules; currently only \"1\" is supported."},"rules":{"type":"object","additionalProperties":true,"description":"Filter expression defining the branch's matching criteria, in prefix notation — the operator first, followed by its operands."}}}}}}}}}}},"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"}}}}}}}}}},"AIDescription":{"type":"object","description":"AI-generated descriptions and documentation for the resource.\n\nThis object contains automatically generated content that helps users\nunderstand the purpose, behavior, and configuration of the resource without\nrequiring them to analyze the technical details. The AI-generated content\nis sanitized and safe for display in the UI.\n","properties":{"summary":{"type":["string","null"],"description":"Brief AI-generated summary of the resource's purpose and functionality.\n\nThis concise description provides a quick overview of what the resource does,\nwhat systems it interacts with, and its primary role in the integration.\nThe summary is suitable for display in list views, dashboards, and other\ncontexts where space is limited.\n\nMaximum length: 10KB\n"},"detailed":{"type":["string","null"],"description":"Comprehensive AI-generated description of the resource's functionality.\n\nThis detailed explanation covers the resource's purpose, configuration details,\ndata flow patterns, filtering logic, and other technical aspects. It provides\nin-depth information suitable for documentation, tooltips, or detailed views\nin the administration interface.\n\nThe content may include HTML formatting for improved readability.\n\nMaximum length: 10KB\n"},"generatedOn":{"type":["string","null"],"format":"date-time","description":"Timestamp indicating when the AI description was generated.\n\nThis field helps track the freshness of the AI-generated content and\ndetermine when it might need to be regenerated due to changes in the\nresource's configuration or behavior.\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix).\n"}}},"ResourceResponse":{"type":"object","description":"Response","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the resource. Format is a 24-character hexadecimal string."},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was created. Set automatically and cannot be modified."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was last updated. Changes whenever any property is modified."},"deletedAt":{"type":["string","null"],"format":"date-time","readOnly":true,"description":"Timestamp when the resource was soft-deleted. When null or absent, the resource is active."}}}}}}
```

## List flows

> Returns all flows in the account.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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":{"After":{"name":"after","in":"query","required":false,"description":"Opaque cursor for forward pagination. Pass the value from the `Link`\nresponse header (`rel=\"next\"`) to fetch the next page.","schema":{"type":"string"}},"Include":{"name":"include","in":"query","required":false,"description":"Comma-separated list of fields to project into each returned record.\nTriggers summary projection: the response contains a minimal identity\nset (`_id`, `name`, plus resource-specific fields) with the requested\nfields added on top. Supports dot notation for nested fields.\nMutually exclusive with `exclude`.","schema":{"type":"string"}},"Exclude":{"name":"exclude","in":"query","required":false,"description":"Comma-separated list of fields to strip from the default response.\nUnlike `include`, does not trigger summary projection — returns the\nfull record with the named fields removed. Protected identity fields\n(e.g. `name`) cannot be stripped. Mutually exclusive with `include`.","schema":{"type":"string"}}},"schemas":{"Flow":{"type":"object","required":["_id","name","disabled","logging","createdAt","lastModified"],"description":"Flow object as returned by the API.","allOf":[{"$ref":"#/components/schemas/FlowBase"},{"$ref":"#/components/schemas/ResourceResponse"},{"type":"object","properties":{"lastExecutedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp of the flow's most recent execution. Absent until the flow has run at least once."},"resolvedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow's open errors were last resolved."},"free":{"type":"boolean","readOnly":true,"description":"When true, the flow is free to run and does not require a paid subscription."},"_templateId":{"type":"string","format":"objectId","readOnly":true,"description":"Template this flow was created from."},"_sourceId":{"type":"string","format":"objectId","readOnly":true,"description":"Source resource this flow was cloned or installed from."}}}]},"FlowBase":{"type":"object","description":"Writable flow fields shared by the request and response schemas.\n\nUse `pageProcessors` for simple linear flows or `routers` for conditional branching — never\ninclude both. The `schedule` field uses Celigo's 6-field cron format (not standard 5-field),\nwhere hours must be explicit comma-separated lists.","properties":{"name":{"type":"string","maxLength":150,"description":"Display name for the flow."},"description":{"type":"string","maxLength":5120,"description":"Free-text description of the flow's purpose."},"_integrationId":{"type":["string","null"],"format":"objectId","description":"Integration this flow belongs to."},"schedule":{"type":["string","null"],"description":"Celigo 6-field cron expression: `? minute hour day-of-month month day-of-week`.\nHours must be explicit comma-separated lists (not `*/4` or `*`). Leave empty for\nevent-driven or webhook-triggered flows."},"timezone":{"type":["string","null"],"description":"IANA timezone for the schedule (e.g. `America/New_York`). Defaults to UTC."},"disabled":{"type":"boolean","description":"When true, scheduled executions are suspended and the flow cannot be triggered.\nRunning jobs are allowed to complete.","default":false},"pageGenerators":{"type":"array","description":"Data sources (exports) that produce pages of records for the flow. Mutually exclusive with\ntop-level `pageProcessors` when `routers` is used.","items":{"$ref":"#/components/schemas/PageGenerator"}},"pageProcessors":{"type":"array","description":"Sequential processing steps (imports, lookups, routers). Mutually exclusive with `routers` —\nuse one or the other, not both.","items":{"$ref":"#/components/schemas/PageProcessor"}},"routers":{"type":"array","description":"Routing configurations that direct records to conditional branches. Mutually exclusive with\ntop-level `pageProcessors` — use one or the other, not both.","items":{"$ref":"#/components/schemas/Router"}},"_runNextFlowIds":{"type":"array","description":"Flow IDs to trigger after this flow completes successfully.","items":{"type":"string","format":"objectId"}},"_runNextExportIds":{"type":"array","description":"Specific exports in other flows to trigger after completion.","items":{"type":"object","properties":{"_flowId":{"type":"string","format":"objectId","description":"Flow containing the export to trigger."},"_exportId":{"type":"string","format":"objectId","description":"Export to execute."}}}},"externalId":{"type":["string","null"],"description":"External identifier for correlating the flow with a record in another system."},"wizardState":{"type":"string","enum":["step2","step3","done"],"description":"Tracks how far the user has progressed through the flow setup wizard in the UI."},"settings":{"type":"object","description":"Custom key-value settings passed to hooks and scripts at runtime.","additionalProperties":true},"_connectorId":{"type":"string","format":"objectId","description":"Connector template this flow was created from."},"runPageGeneratorsInParallel":{"type":"boolean","description":"When true, all page generators start simultaneously instead of sequentially."},"autoResolveMatchingTraceKeys":{"type":"boolean","description":"When true, new errors with trace keys matching existing open errors are auto-resolved."},"isAbstract":{"type":"boolean","description":"Marks this as an abstract (multi-instance) flow — a reusable template that cannot be\nexecuted directly. Instance flows reference it via `_abstractFlowId` and provide `overrides`.\n\nConstraints: top-level `pageProcessors` are not allowed (use `routers`), cannot reference\nanother abstract flow, cannot be a \"run next\" target, and cannot be unset while instances exist."},"_abstractFlowId":{"type":"string","format":"objectId","description":"Abstract flow this instance inherits from. Immutable once set. The instance inherits\nthe flow graph and uses `overrides` to customize connections, schedules, and hooks."},"overrides":{"$ref":"#/components/schemas/Overrides"},"overridesHelper":{"$ref":"#/components/schemas/OverridesHelper"},"hidden":{"type":"boolean","description":"When true, the flow is hidden from standard UI views but remains executable via API."},"_flowGroupingId":{"type":["string","null"],"format":"objectId","description":"Flow grouping for organizing related flows in the UI. References an entry in the\nintegration's `flowGroupings` array (not a standalone collection); invalid ids are\nsilently dropped by the server."},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Coordinates delta timing so this flow's checkpoint stays behind the referenced flow.\nUsed for parent-child data relationships where the parent must sync first."},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Like `_keepDeltaBehindFlowId` but targets a specific export within a flow."},"aiDescription":{"$ref":"#/components/schemas/AIDescription"},"aliases":{"type":"array","description":"Named aliases that map to specific resources within the flow.","items":{"type":"object","properties":{"alias":{"type":"string","description":"Alias name."},"_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":"When true, this flow is in draft mode and not yet published."},"draftExpiresAt":{"type":"string","format":"date-time","description":"Timestamp when the draft version expires."},"logging":{"type":"object","description":"Flow-level logging configuration.","properties":{"mode":{"type":"string","description":"Logging verbosity level.","enum":["accountLevel","basic","detailed"]},"debugUntil":{"type":"string","format":"date-time","description":"Temporary debug-level logging until this timestamp (max 1 hour from now)."}}},"numInstances":{"type":"integer","description":"Number of instance flows derived from this abstract flow.","readOnly":true},"preSave":{"type":"object","description":"Pre-save hook that runs a script before persisting flow changes.","properties":{"function":{"type":"string","description":"Function name to invoke."},"_scriptId":{"type":"string","format":"objectId","description":"Script containing the pre-save function."}}},"settingsForm":{"type":"object","description":"Form definition for collecting flow-level settings from users in the UI.","additionalProperties":true}}},"PageGenerator":{"type":"object","description":"A data source that produces pages of records for the flow. Page generators are the\nentry points of a flow; each references an export, can carry its own schedule, and\nmultiple generators can run in parallel when the flow enables it.","required":["_exportId"],"properties":{"_exportId":{"type":"string","format":"objectId","description":"Export that retrieves data from the source system. The server rejects page\ngenerator entries without a valid export reference."},"schedule":{"type":"string","description":"Cron expression for this specific generator, overriding the flow's main schedule.\nWhen omitted, the generator inherits the flow's schedule."},"skipRetries":{"type":"boolean","description":"When true, failed records from this generator are not retried — errors are logged\nand the flow continues. When false, failed records are retried per platform policy."},"setupInProgress":{"type":"boolean","description":"When true, the generator's configuration is still being set up in the UI and the step is not yet runnable."},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Coordinates delta timing so this generator's checkpoint stays behind the referenced\nflow, preventing child records from being processed before their parents."},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Like `_keepDeltaBehindFlowId` but targets a specific export's delta timestamp."},"__startDateHelper":{"type":"string","description":"Internal helper field for managing scheduled start dates."}}},"PageProcessor":{"type":"object","description":"A processing step that operates on pages of records within a flow. Processors are\neither lookups (`type: export`) that enrich records or imports (`type: import`) that\nwrite records to a destination, and execute sequentially unless routed into branches.","required":["type"],"properties":{"type":{"type":"string","description":"Selects whether this step runs a lookup export or an import, and which reference field applies.","enum":["export","import"]},"_exportId":{"type":"string","format":"objectId","description":"Lookup export that enriches incoming records. Required when `type` is `export`;\nthe referenced export must be configured as a lookup (`isLookup: true`)."},"_importId":{"type":"string","format":"objectId","description":"Import that writes records to the destination system. Required when `type` is `import`."},"proceedOnFailure":{"type":"boolean","description":"When true, records that fail in this processor continue to subsequent steps and the\nerror is logged. When false, failed records stop at this step."},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"hooks":{"type":"object","description":"Custom code hooks extending this processor's behavior.","properties":{"postResponseMap":{"type":"object","description":"Hook that runs after the step's response mapping completes.","properties":{"function":{"type":"string","description":"Function to invoke within the referenced script."},"_scriptId":{"type":"string","format":"objectId","description":"Script containing the hook function named in `function`."}}}}},"setupInProgress":{"type":"boolean","description":"When true, the processor's configuration is still being set up in the UI and the step is not yet runnable."}},"if":{"properties":{"type":{"const":"export"}},"required":["type"]},"then":{"required":["_exportId"]},"else":{"if":{"properties":{"type":{"const":"import"}},"required":["type"]},"then":{"required":["_importId"]}}},"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":"When true, marks this entry as an internal identifier."}}}},"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":"When true, marks this entry as an internal identifier."}}}},"_id":{"type":"boolean","description":"When true, marks this entry as an internal identifier."}}}},"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.","enum":["first_matching_branch","all_matching_branches"],"default":"first_matching_branch"},"routeRecordsUsing":{"type":"string","description":"Method used to evaluate routing criteria.","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","description":"Version of the filter expression format used by the rules; currently only \"1\" is supported."},"rules":{"type":"object","additionalProperties":true,"description":"Filter expression defining the matching criteria, in prefix notation — the operator first, followed by its operands, which may be nested expressions."}}},"groupByFields":{"type":"array","description":"Override grouping fields","items":{"type":"string"}},"test":{"type":"object","description":"Override test mode settings","properties":{"limit":{"type":"integer","description":"Overrides the test-mode record cap on the abstract flow's export — the total number of records a test run processes."}}},"delta":{"type":"object","description":"Override delta configuration","properties":{"dateField":{"type":"string","description":"Overrides the delta date field on the abstract flow's export — the record timestamp field(s) compared against the last successful run time to identify changed records. Accepts a single field or multiple comma-separated fields."},"dateFormat":{"type":"string","description":"Overrides the moment.js format string applied to the delta cutoff timestamp; ISO 8601 is used when unset."},"startDate":{"type":"string","description":"Overrides the fixed start timestamp used for the delta window on the abstract flow's export, in place of the last successful run time."},"lagOffset":{"type":"integer","description":"Overrides the buffer in milliseconds subtracted from the last successful run timestamp, creating an overlapping window that catches late-propagating records."},"endDateField":{"type":"string","description":"Overrides the record timestamp field used as the upper bound of the delta window on the abstract flow's export."}}},"once":{"type":"object","description":"Override once export settings","properties":{"booleanField":{"type":"string","description":"Overrides the once-mode tracking field on the abstract flow's export — the boolean field in the source system that is false for unprocessed records and set to true after successful processing."}}},"valueDelta":{"type":"object","description":"Override value delta settings","properties":{"exportedField":{"type":"string","description":"Overrides the field that tracks the last exported value on the abstract flow's export."},"pendingField":{"type":"string","description":"Overrides the field that tracks the pending (not yet exported) value on the abstract flow's export."}}},"webhook":{"type":"object","description":"Override webhook configuration","properties":{"token_crypt":{"type":"string","description":"Encrypted form of the webhook verification token, stored at rest."},"token_salt":{"type":"string","description":"Salt used to encrypt the corresponding webhook token."},"path":{"type":"string","description":"Overrides the location of the verification token on the abstract flow's webhook export — a JSON path into the request body or a query parameter name."},"key_crypt":{"type":"string","description":"Encrypted form of the webhook HMAC or public key, stored at rest."},"key_salt":{"type":"string","description":"Salt used to encrypt the corresponding webhook key."},"header":{"type":"string","description":"Overrides the name of the request header that carries the HMAC signature on the abstract flow's webhook export."},"username":{"type":"string","description":"Overrides the username used for basic-auth webhook verification on the abstract flow's export."},"password_crypt":{"type":"string","description":"Encrypted form of the basic-auth webhook password, stored at rest."},"password_salt":{"type":"string","description":"Salt used to encrypt the corresponding webhook password."},"successStatusCode":{"type":"integer","description":"Overrides the HTTP status code returned to the webhook caller after successful processing."},"successBody":{"type":"string","description":"Overrides the response body returned to the webhook caller after successful processing; ignored when the status code is 204."},"successMediaType":{"type":"string","description":"Overrides the Content-Type of successful webhook responses; must match the format of the success body."}}},"distributed":{"type":"object","description":"Override distributed processing settings","properties":{"bearerToken_crypt":{"type":"string","description":"Encrypted form of the distributed export's bearer token, stored at rest."},"bearerToken_salt":{"type":"string","description":"Salt used to encrypt the corresponding bearer token."}}},"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","description":"Overrides the ID lock template on the abstract flow's import — a handlebars template that generates a lock key so records resolving to the same key are not submitted concurrently."},"dataURITemplate":{"type":"string","description":"Overrides the data URI template on the abstract flow's import — a handlebars template that builds a link back to each record in the destination application's UI for error tracking."},"pathToMany":{"type":"string","description":"Overrides the one-to-many path on the abstract flow's import — the JSON path to child records within each parent record."},"blobKeyPath":{"type":"string","description":"Overrides the blob key path on the abstract flow's import — the path in the input record that holds the blob key identifying file content to import."},"filter":{"type":"object","additionalProperties":true,"description":"Overrides the filter on the abstract flow's import, which selects which incoming records are sent to the destination system."},"traceKeyTemplate":{"type":"string","description":"Overrides the trace key template on the abstract flow's import — a handlebars template controlling how each record's unique trace key is generated."},"parsers":{"type":"array","items":{"type":"object"},"description":"Overrides the parser configurations on the abstract flow's import."},"hooks":{"type":"object","additionalProperties":true,"description":"Overrides the hook configurations on the abstract flow's import — custom JavaScript hooks that run at fixed points in the import lifecycle."},"responseTransform":{"type":"object","additionalProperties":true,"description":"Overrides the response transform on the abstract flow's import, which reshapes the destination system's response after records are imported."},"mapping":{"type":"object","additionalProperties":true,"description":"Overrides the Mapper 1.0 mapping configuration on the abstract flow's import."},"mappings":{"type":"array","items":{"type":"object"},"description":"Overrides the Mapper 2.0 field mappings on the abstract flow's import, which transform incoming records into the destination system's field structure."},"lookups":{"type":"array","items":{"type":"object"},"description":"Overrides the lookup definitions on the abstract flow's import, referenced by its field mappings."},"settingsForm":{"type":"object","additionalProperties":true,"description":"Overrides the settings form definition on the abstract flow's import, which prompts users for values stored in `settings`."},"preSave":{"type":"object","additionalProperties":true,"description":"Overrides the preSave hook on the abstract flow's import — a JavaScript hook that executes before the resource is saved."},"settings":{"type":"object","additionalProperties":true,"description":"Overrides the custom settings on the abstract flow's import, accessible to hooks, filters, mappings, and handlebars templates at runtime."}}}},"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","description":"Reference to the script resource containing the routing logic used in place of the abstract router's script."},"function":{"type":"string","description":"Function name within the script that returns the branch name for each record."}}},"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":"Overrides the branch's display name within the router."},"description":{"type":"string","description":"Overrides the branch's description explaining its purpose and criteria."},"inputFilter":{"type":"object","description":"Overrides the branch's input filter — the criteria that determine which records are routed to this branch.","properties":{"version":{"type":"string","description":"Version of the filter expression format used by the rules; currently only \"1\" is supported."},"rules":{"type":"object","additionalProperties":true,"description":"Filter expression defining the branch's matching criteria, in prefix notation — the operator first, followed by its operands."}}}}}}}}}}},"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"}}}}}}}}}},"AIDescription":{"type":"object","description":"AI-generated descriptions and documentation for the resource.\n\nThis object contains automatically generated content that helps users\nunderstand the purpose, behavior, and configuration of the resource without\nrequiring them to analyze the technical details. The AI-generated content\nis sanitized and safe for display in the UI.\n","properties":{"summary":{"type":["string","null"],"description":"Brief AI-generated summary of the resource's purpose and functionality.\n\nThis concise description provides a quick overview of what the resource does,\nwhat systems it interacts with, and its primary role in the integration.\nThe summary is suitable for display in list views, dashboards, and other\ncontexts where space is limited.\n\nMaximum length: 10KB\n"},"detailed":{"type":["string","null"],"description":"Comprehensive AI-generated description of the resource's functionality.\n\nThis detailed explanation covers the resource's purpose, configuration details,\ndata flow patterns, filtering logic, and other technical aspects. It provides\nin-depth information suitable for documentation, tooltips, or detailed views\nin the administration interface.\n\nThe content may include HTML formatting for improved readability.\n\nMaximum length: 10KB\n"},"generatedOn":{"type":["string","null"],"format":"date-time","description":"Timestamp indicating when the AI description was generated.\n\nThis field helps track the freshness of the AI-generated content and\ndetermine when it might need to be regenerated due to changes in the\nresource's configuration or behavior.\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix).\n"}}},"ResourceResponse":{"type":"object","description":"Response","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the resource. Format is a 24-character hexadecimal string."},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was created. Set automatically and cannot be modified."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was last updated. Changes whenever any property is modified."},"deletedAt":{"type":["string","null"],"format":"date-time","readOnly":true,"description":"Timestamp when the resource was soft-deleted. When null or absent, the resource is active."}}}},"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 all flows in the account.","operationId":"listFlows","tags":["Flows"],"parameters":[{"name":"_abstractFlowId","in":"query","description":"Filter to instance flows that inherit from this abstract (multi-instance) flow.","schema":{"type":"string","format":"objectId"}},{"name":"externalId","in":"query","description":"Filter to flows matching this exact external identifier.","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Maximum number of flows to return per page.","schema":{"type":"integer","minimum":1}},{"$ref":"#/components/parameters/After"},{"$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.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Flow"}}}}},"204":{"description":"No flows exist in the account."},"401":{"$ref":"#/components/responses/401-unauthorized"}}}}}}
```

## Create a flow

> Creates a new flow. Flows are created enabled (\`disabled: false\`) by default — set\
> \`disabled: true\` on create if the flow is not ready to run.\
> \
> At minimum, provide \`name\` and \`\_integrationId\`. Do not leave the flow enabled with a\
> \`schedule\` unless it is fully configured — it will start executing on schedule. For\
> abstract/instance patterns, create the abstract flow first, then create instances with\
> \`\_abstractFlowId\`.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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 for creating or updating a flow.\n\nUse `pageProcessors` for simple linear flows or `routers` for conditional branching — never\ninclude both. The `schedule` field uses Celigo's 6-field cron format (not standard 5-field),\nwhere hours must be explicit comma-separated lists.","required":["name"],"allOf":[{"$ref":"#/components/schemas/FlowBase"}]},"FlowBase":{"type":"object","description":"Writable flow fields shared by the request and response schemas.\n\nUse `pageProcessors` for simple linear flows or `routers` for conditional branching — never\ninclude both. The `schedule` field uses Celigo's 6-field cron format (not standard 5-field),\nwhere hours must be explicit comma-separated lists.","properties":{"name":{"type":"string","maxLength":150,"description":"Display name for the flow."},"description":{"type":"string","maxLength":5120,"description":"Free-text description of the flow's purpose."},"_integrationId":{"type":["string","null"],"format":"objectId","description":"Integration this flow belongs to."},"schedule":{"type":["string","null"],"description":"Celigo 6-field cron expression: `? minute hour day-of-month month day-of-week`.\nHours must be explicit comma-separated lists (not `*/4` or `*`). Leave empty for\nevent-driven or webhook-triggered flows."},"timezone":{"type":["string","null"],"description":"IANA timezone for the schedule (e.g. `America/New_York`). Defaults to UTC."},"disabled":{"type":"boolean","description":"When true, scheduled executions are suspended and the flow cannot be triggered.\nRunning jobs are allowed to complete.","default":false},"pageGenerators":{"type":"array","description":"Data sources (exports) that produce pages of records for the flow. Mutually exclusive with\ntop-level `pageProcessors` when `routers` is used.","items":{"$ref":"#/components/schemas/PageGenerator"}},"pageProcessors":{"type":"array","description":"Sequential processing steps (imports, lookups, routers). Mutually exclusive with `routers` —\nuse one or the other, not both.","items":{"$ref":"#/components/schemas/PageProcessor"}},"routers":{"type":"array","description":"Routing configurations that direct records to conditional branches. Mutually exclusive with\ntop-level `pageProcessors` — use one or the other, not both.","items":{"$ref":"#/components/schemas/Router"}},"_runNextFlowIds":{"type":"array","description":"Flow IDs to trigger after this flow completes successfully.","items":{"type":"string","format":"objectId"}},"_runNextExportIds":{"type":"array","description":"Specific exports in other flows to trigger after completion.","items":{"type":"object","properties":{"_flowId":{"type":"string","format":"objectId","description":"Flow containing the export to trigger."},"_exportId":{"type":"string","format":"objectId","description":"Export to execute."}}}},"externalId":{"type":["string","null"],"description":"External identifier for correlating the flow with a record in another system."},"wizardState":{"type":"string","enum":["step2","step3","done"],"description":"Tracks how far the user has progressed through the flow setup wizard in the UI."},"settings":{"type":"object","description":"Custom key-value settings passed to hooks and scripts at runtime.","additionalProperties":true},"_connectorId":{"type":"string","format":"objectId","description":"Connector template this flow was created from."},"runPageGeneratorsInParallel":{"type":"boolean","description":"When true, all page generators start simultaneously instead of sequentially."},"autoResolveMatchingTraceKeys":{"type":"boolean","description":"When true, new errors with trace keys matching existing open errors are auto-resolved."},"isAbstract":{"type":"boolean","description":"Marks this as an abstract (multi-instance) flow — a reusable template that cannot be\nexecuted directly. Instance flows reference it via `_abstractFlowId` and provide `overrides`.\n\nConstraints: top-level `pageProcessors` are not allowed (use `routers`), cannot reference\nanother abstract flow, cannot be a \"run next\" target, and cannot be unset while instances exist."},"_abstractFlowId":{"type":"string","format":"objectId","description":"Abstract flow this instance inherits from. Immutable once set. The instance inherits\nthe flow graph and uses `overrides` to customize connections, schedules, and hooks."},"overrides":{"$ref":"#/components/schemas/Overrides"},"overridesHelper":{"$ref":"#/components/schemas/OverridesHelper"},"hidden":{"type":"boolean","description":"When true, the flow is hidden from standard UI views but remains executable via API."},"_flowGroupingId":{"type":["string","null"],"format":"objectId","description":"Flow grouping for organizing related flows in the UI. References an entry in the\nintegration's `flowGroupings` array (not a standalone collection); invalid ids are\nsilently dropped by the server."},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Coordinates delta timing so this flow's checkpoint stays behind the referenced flow.\nUsed for parent-child data relationships where the parent must sync first."},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Like `_keepDeltaBehindFlowId` but targets a specific export within a flow."},"aiDescription":{"$ref":"#/components/schemas/AIDescription"},"aliases":{"type":"array","description":"Named aliases that map to specific resources within the flow.","items":{"type":"object","properties":{"alias":{"type":"string","description":"Alias name."},"_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":"When true, this flow is in draft mode and not yet published."},"draftExpiresAt":{"type":"string","format":"date-time","description":"Timestamp when the draft version expires."},"logging":{"type":"object","description":"Flow-level logging configuration.","properties":{"mode":{"type":"string","description":"Logging verbosity level.","enum":["accountLevel","basic","detailed"]},"debugUntil":{"type":"string","format":"date-time","description":"Temporary debug-level logging until this timestamp (max 1 hour from now)."}}},"numInstances":{"type":"integer","description":"Number of instance flows derived from this abstract flow.","readOnly":true},"preSave":{"type":"object","description":"Pre-save hook that runs a script before persisting flow changes.","properties":{"function":{"type":"string","description":"Function name to invoke."},"_scriptId":{"type":"string","format":"objectId","description":"Script containing the pre-save function."}}},"settingsForm":{"type":"object","description":"Form definition for collecting flow-level settings from users in the UI.","additionalProperties":true}}},"PageGenerator":{"type":"object","description":"A data source that produces pages of records for the flow. Page generators are the\nentry points of a flow; each references an export, can carry its own schedule, and\nmultiple generators can run in parallel when the flow enables it.","required":["_exportId"],"properties":{"_exportId":{"type":"string","format":"objectId","description":"Export that retrieves data from the source system. The server rejects page\ngenerator entries without a valid export reference."},"schedule":{"type":"string","description":"Cron expression for this specific generator, overriding the flow's main schedule.\nWhen omitted, the generator inherits the flow's schedule."},"skipRetries":{"type":"boolean","description":"When true, failed records from this generator are not retried — errors are logged\nand the flow continues. When false, failed records are retried per platform policy."},"setupInProgress":{"type":"boolean","description":"When true, the generator's configuration is still being set up in the UI and the step is not yet runnable."},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Coordinates delta timing so this generator's checkpoint stays behind the referenced\nflow, preventing child records from being processed before their parents."},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Like `_keepDeltaBehindFlowId` but targets a specific export's delta timestamp."},"__startDateHelper":{"type":"string","description":"Internal helper field for managing scheduled start dates."}}},"PageProcessor":{"type":"object","description":"A processing step that operates on pages of records within a flow. Processors are\neither lookups (`type: export`) that enrich records or imports (`type: import`) that\nwrite records to a destination, and execute sequentially unless routed into branches.","required":["type"],"properties":{"type":{"type":"string","description":"Selects whether this step runs a lookup export or an import, and which reference field applies.","enum":["export","import"]},"_exportId":{"type":"string","format":"objectId","description":"Lookup export that enriches incoming records. Required when `type` is `export`;\nthe referenced export must be configured as a lookup (`isLookup: true`)."},"_importId":{"type":"string","format":"objectId","description":"Import that writes records to the destination system. Required when `type` is `import`."},"proceedOnFailure":{"type":"boolean","description":"When true, records that fail in this processor continue to subsequent steps and the\nerror is logged. When false, failed records stop at this step."},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"hooks":{"type":"object","description":"Custom code hooks extending this processor's behavior.","properties":{"postResponseMap":{"type":"object","description":"Hook that runs after the step's response mapping completes.","properties":{"function":{"type":"string","description":"Function to invoke within the referenced script."},"_scriptId":{"type":"string","format":"objectId","description":"Script containing the hook function named in `function`."}}}}},"setupInProgress":{"type":"boolean","description":"When true, the processor's configuration is still being set up in the UI and the step is not yet runnable."}},"if":{"properties":{"type":{"const":"export"}},"required":["type"]},"then":{"required":["_exportId"]},"else":{"if":{"properties":{"type":{"const":"import"}},"required":["type"]},"then":{"required":["_importId"]}}},"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":"When true, marks this entry as an internal identifier."}}}},"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":"When true, marks this entry as an internal identifier."}}}},"_id":{"type":"boolean","description":"When true, marks this entry as an internal identifier."}}}},"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.","enum":["first_matching_branch","all_matching_branches"],"default":"first_matching_branch"},"routeRecordsUsing":{"type":"string","description":"Method used to evaluate routing criteria.","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","description":"Version of the filter expression format used by the rules; currently only \"1\" is supported."},"rules":{"type":"object","additionalProperties":true,"description":"Filter expression defining the matching criteria, in prefix notation — the operator first, followed by its operands, which may be nested expressions."}}},"groupByFields":{"type":"array","description":"Override grouping fields","items":{"type":"string"}},"test":{"type":"object","description":"Override test mode settings","properties":{"limit":{"type":"integer","description":"Overrides the test-mode record cap on the abstract flow's export — the total number of records a test run processes."}}},"delta":{"type":"object","description":"Override delta configuration","properties":{"dateField":{"type":"string","description":"Overrides the delta date field on the abstract flow's export — the record timestamp field(s) compared against the last successful run time to identify changed records. Accepts a single field or multiple comma-separated fields."},"dateFormat":{"type":"string","description":"Overrides the moment.js format string applied to the delta cutoff timestamp; ISO 8601 is used when unset."},"startDate":{"type":"string","description":"Overrides the fixed start timestamp used for the delta window on the abstract flow's export, in place of the last successful run time."},"lagOffset":{"type":"integer","description":"Overrides the buffer in milliseconds subtracted from the last successful run timestamp, creating an overlapping window that catches late-propagating records."},"endDateField":{"type":"string","description":"Overrides the record timestamp field used as the upper bound of the delta window on the abstract flow's export."}}},"once":{"type":"object","description":"Override once export settings","properties":{"booleanField":{"type":"string","description":"Overrides the once-mode tracking field on the abstract flow's export — the boolean field in the source system that is false for unprocessed records and set to true after successful processing."}}},"valueDelta":{"type":"object","description":"Override value delta settings","properties":{"exportedField":{"type":"string","description":"Overrides the field that tracks the last exported value on the abstract flow's export."},"pendingField":{"type":"string","description":"Overrides the field that tracks the pending (not yet exported) value on the abstract flow's export."}}},"webhook":{"type":"object","description":"Override webhook configuration","properties":{"token_crypt":{"type":"string","description":"Encrypted form of the webhook verification token, stored at rest."},"token_salt":{"type":"string","description":"Salt used to encrypt the corresponding webhook token."},"path":{"type":"string","description":"Overrides the location of the verification token on the abstract flow's webhook export — a JSON path into the request body or a query parameter name."},"key_crypt":{"type":"string","description":"Encrypted form of the webhook HMAC or public key, stored at rest."},"key_salt":{"type":"string","description":"Salt used to encrypt the corresponding webhook key."},"header":{"type":"string","description":"Overrides the name of the request header that carries the HMAC signature on the abstract flow's webhook export."},"username":{"type":"string","description":"Overrides the username used for basic-auth webhook verification on the abstract flow's export."},"password_crypt":{"type":"string","description":"Encrypted form of the basic-auth webhook password, stored at rest."},"password_salt":{"type":"string","description":"Salt used to encrypt the corresponding webhook password."},"successStatusCode":{"type":"integer","description":"Overrides the HTTP status code returned to the webhook caller after successful processing."},"successBody":{"type":"string","description":"Overrides the response body returned to the webhook caller after successful processing; ignored when the status code is 204."},"successMediaType":{"type":"string","description":"Overrides the Content-Type of successful webhook responses; must match the format of the success body."}}},"distributed":{"type":"object","description":"Override distributed processing settings","properties":{"bearerToken_crypt":{"type":"string","description":"Encrypted form of the distributed export's bearer token, stored at rest."},"bearerToken_salt":{"type":"string","description":"Salt used to encrypt the corresponding bearer token."}}},"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","description":"Overrides the ID lock template on the abstract flow's import — a handlebars template that generates a lock key so records resolving to the same key are not submitted concurrently."},"dataURITemplate":{"type":"string","description":"Overrides the data URI template on the abstract flow's import — a handlebars template that builds a link back to each record in the destination application's UI for error tracking."},"pathToMany":{"type":"string","description":"Overrides the one-to-many path on the abstract flow's import — the JSON path to child records within each parent record."},"blobKeyPath":{"type":"string","description":"Overrides the blob key path on the abstract flow's import — the path in the input record that holds the blob key identifying file content to import."},"filter":{"type":"object","additionalProperties":true,"description":"Overrides the filter on the abstract flow's import, which selects which incoming records are sent to the destination system."},"traceKeyTemplate":{"type":"string","description":"Overrides the trace key template on the abstract flow's import — a handlebars template controlling how each record's unique trace key is generated."},"parsers":{"type":"array","items":{"type":"object"},"description":"Overrides the parser configurations on the abstract flow's import."},"hooks":{"type":"object","additionalProperties":true,"description":"Overrides the hook configurations on the abstract flow's import — custom JavaScript hooks that run at fixed points in the import lifecycle."},"responseTransform":{"type":"object","additionalProperties":true,"description":"Overrides the response transform on the abstract flow's import, which reshapes the destination system's response after records are imported."},"mapping":{"type":"object","additionalProperties":true,"description":"Overrides the Mapper 1.0 mapping configuration on the abstract flow's import."},"mappings":{"type":"array","items":{"type":"object"},"description":"Overrides the Mapper 2.0 field mappings on the abstract flow's import, which transform incoming records into the destination system's field structure."},"lookups":{"type":"array","items":{"type":"object"},"description":"Overrides the lookup definitions on the abstract flow's import, referenced by its field mappings."},"settingsForm":{"type":"object","additionalProperties":true,"description":"Overrides the settings form definition on the abstract flow's import, which prompts users for values stored in `settings`."},"preSave":{"type":"object","additionalProperties":true,"description":"Overrides the preSave hook on the abstract flow's import — a JavaScript hook that executes before the resource is saved."},"settings":{"type":"object","additionalProperties":true,"description":"Overrides the custom settings on the abstract flow's import, accessible to hooks, filters, mappings, and handlebars templates at runtime."}}}},"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","description":"Reference to the script resource containing the routing logic used in place of the abstract router's script."},"function":{"type":"string","description":"Function name within the script that returns the branch name for each record."}}},"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":"Overrides the branch's display name within the router."},"description":{"type":"string","description":"Overrides the branch's description explaining its purpose and criteria."},"inputFilter":{"type":"object","description":"Overrides the branch's input filter — the criteria that determine which records are routed to this branch.","properties":{"version":{"type":"string","description":"Version of the filter expression format used by the rules; currently only \"1\" is supported."},"rules":{"type":"object","additionalProperties":true,"description":"Filter expression defining the branch's matching criteria, in prefix notation — the operator first, followed by its operands."}}}}}}}}}}},"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"}}}}}}}}}},"AIDescription":{"type":"object","description":"AI-generated descriptions and documentation for the resource.\n\nThis object contains automatically generated content that helps users\nunderstand the purpose, behavior, and configuration of the resource without\nrequiring them to analyze the technical details. The AI-generated content\nis sanitized and safe for display in the UI.\n","properties":{"summary":{"type":["string","null"],"description":"Brief AI-generated summary of the resource's purpose and functionality.\n\nThis concise description provides a quick overview of what the resource does,\nwhat systems it interacts with, and its primary role in the integration.\nThe summary is suitable for display in list views, dashboards, and other\ncontexts where space is limited.\n\nMaximum length: 10KB\n"},"detailed":{"type":["string","null"],"description":"Comprehensive AI-generated description of the resource's functionality.\n\nThis detailed explanation covers the resource's purpose, configuration details,\ndata flow patterns, filtering logic, and other technical aspects. It provides\nin-depth information suitable for documentation, tooltips, or detailed views\nin the administration interface.\n\nThe content may include HTML formatting for improved readability.\n\nMaximum length: 10KB\n"},"generatedOn":{"type":["string","null"],"format":"date-time","description":"Timestamp indicating when the AI description was generated.\n\nThis field helps track the freshness of the AI-generated content and\ndetermine when it might need to be regenerated due to changes in the\nresource's configuration or behavior.\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix).\n"}}},"Flow":{"type":"object","required":["_id","name","disabled","logging","createdAt","lastModified"],"description":"Flow object as returned by the API.","allOf":[{"$ref":"#/components/schemas/FlowBase"},{"$ref":"#/components/schemas/ResourceResponse"},{"type":"object","properties":{"lastExecutedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp of the flow's most recent execution. Absent until the flow has run at least once."},"resolvedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow's open errors were last resolved."},"free":{"type":"boolean","readOnly":true,"description":"When true, the flow is free to run and does not require a paid subscription."},"_templateId":{"type":"string","format":"objectId","readOnly":true,"description":"Template this flow was created from."},"_sourceId":{"type":"string","format":"objectId","readOnly":true,"description":"Source resource this flow was cloned or installed from."}}}]},"ResourceResponse":{"type":"object","description":"Response","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the resource. Format is a 24-character hexadecimal string."},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was created. Set automatically and cannot be modified."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was last updated. Changes whenever any property is modified."},"deletedAt":{"type":["string","null"],"format":"date-time","readOnly":true,"description":"Timestamp when the resource was soft-deleted. When null or absent, the resource is active."}}},"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. Flows are created enabled (`disabled: false`) by default — set\n`disabled: true` on create if the flow is not ready to run.\n\nAt minimum, provide `name` and `_integrationId`. Do not leave the flow enabled with a\n`schedule` unless it is fully configured — it will start executing on schedule. For\nabstract/instance patterns, create the abstract flow first, then create instances with\n`_abstractFlowId`.","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/Flow"}}}},"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 flow, including its page generators, processors,\
> routers, schedule, and all nested settings.\
> \
> Walk \`pageGenerators\[].\_exportId\` and \`pageProcessors\[].\_importId\` (or\
> \`routers\[].branches\[].pageProcessors\[]\`) to discover the exports and imports wired into\
> the flow. For the full resource objects, use \`GET /v1/flows/{\_id}/descendants\` instead of\
> fetching each one individually. Instance flows (\`\_abstractFlowId\` is set) have sparse\
> top-level fields because the runtime merges them with the abstract flow's config.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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":{"Flow":{"type":"object","required":["_id","name","disabled","logging","createdAt","lastModified"],"description":"Flow object as returned by the API.","allOf":[{"$ref":"#/components/schemas/FlowBase"},{"$ref":"#/components/schemas/ResourceResponse"},{"type":"object","properties":{"lastExecutedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp of the flow's most recent execution. Absent until the flow has run at least once."},"resolvedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow's open errors were last resolved."},"free":{"type":"boolean","readOnly":true,"description":"When true, the flow is free to run and does not require a paid subscription."},"_templateId":{"type":"string","format":"objectId","readOnly":true,"description":"Template this flow was created from."},"_sourceId":{"type":"string","format":"objectId","readOnly":true,"description":"Source resource this flow was cloned or installed from."}}}]},"FlowBase":{"type":"object","description":"Writable flow fields shared by the request and response schemas.\n\nUse `pageProcessors` for simple linear flows or `routers` for conditional branching — never\ninclude both. The `schedule` field uses Celigo's 6-field cron format (not standard 5-field),\nwhere hours must be explicit comma-separated lists.","properties":{"name":{"type":"string","maxLength":150,"description":"Display name for the flow."},"description":{"type":"string","maxLength":5120,"description":"Free-text description of the flow's purpose."},"_integrationId":{"type":["string","null"],"format":"objectId","description":"Integration this flow belongs to."},"schedule":{"type":["string","null"],"description":"Celigo 6-field cron expression: `? minute hour day-of-month month day-of-week`.\nHours must be explicit comma-separated lists (not `*/4` or `*`). Leave empty for\nevent-driven or webhook-triggered flows."},"timezone":{"type":["string","null"],"description":"IANA timezone for the schedule (e.g. `America/New_York`). Defaults to UTC."},"disabled":{"type":"boolean","description":"When true, scheduled executions are suspended and the flow cannot be triggered.\nRunning jobs are allowed to complete.","default":false},"pageGenerators":{"type":"array","description":"Data sources (exports) that produce pages of records for the flow. Mutually exclusive with\ntop-level `pageProcessors` when `routers` is used.","items":{"$ref":"#/components/schemas/PageGenerator"}},"pageProcessors":{"type":"array","description":"Sequential processing steps (imports, lookups, routers). Mutually exclusive with `routers` —\nuse one or the other, not both.","items":{"$ref":"#/components/schemas/PageProcessor"}},"routers":{"type":"array","description":"Routing configurations that direct records to conditional branches. Mutually exclusive with\ntop-level `pageProcessors` — use one or the other, not both.","items":{"$ref":"#/components/schemas/Router"}},"_runNextFlowIds":{"type":"array","description":"Flow IDs to trigger after this flow completes successfully.","items":{"type":"string","format":"objectId"}},"_runNextExportIds":{"type":"array","description":"Specific exports in other flows to trigger after completion.","items":{"type":"object","properties":{"_flowId":{"type":"string","format":"objectId","description":"Flow containing the export to trigger."},"_exportId":{"type":"string","format":"objectId","description":"Export to execute."}}}},"externalId":{"type":["string","null"],"description":"External identifier for correlating the flow with a record in another system."},"wizardState":{"type":"string","enum":["step2","step3","done"],"description":"Tracks how far the user has progressed through the flow setup wizard in the UI."},"settings":{"type":"object","description":"Custom key-value settings passed to hooks and scripts at runtime.","additionalProperties":true},"_connectorId":{"type":"string","format":"objectId","description":"Connector template this flow was created from."},"runPageGeneratorsInParallel":{"type":"boolean","description":"When true, all page generators start simultaneously instead of sequentially."},"autoResolveMatchingTraceKeys":{"type":"boolean","description":"When true, new errors with trace keys matching existing open errors are auto-resolved."},"isAbstract":{"type":"boolean","description":"Marks this as an abstract (multi-instance) flow — a reusable template that cannot be\nexecuted directly. Instance flows reference it via `_abstractFlowId` and provide `overrides`.\n\nConstraints: top-level `pageProcessors` are not allowed (use `routers`), cannot reference\nanother abstract flow, cannot be a \"run next\" target, and cannot be unset while instances exist."},"_abstractFlowId":{"type":"string","format":"objectId","description":"Abstract flow this instance inherits from. Immutable once set. The instance inherits\nthe flow graph and uses `overrides` to customize connections, schedules, and hooks."},"overrides":{"$ref":"#/components/schemas/Overrides"},"overridesHelper":{"$ref":"#/components/schemas/OverridesHelper"},"hidden":{"type":"boolean","description":"When true, the flow is hidden from standard UI views but remains executable via API."},"_flowGroupingId":{"type":["string","null"],"format":"objectId","description":"Flow grouping for organizing related flows in the UI. References an entry in the\nintegration's `flowGroupings` array (not a standalone collection); invalid ids are\nsilently dropped by the server."},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Coordinates delta timing so this flow's checkpoint stays behind the referenced flow.\nUsed for parent-child data relationships where the parent must sync first."},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Like `_keepDeltaBehindFlowId` but targets a specific export within a flow."},"aiDescription":{"$ref":"#/components/schemas/AIDescription"},"aliases":{"type":"array","description":"Named aliases that map to specific resources within the flow.","items":{"type":"object","properties":{"alias":{"type":"string","description":"Alias name."},"_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":"When true, this flow is in draft mode and not yet published."},"draftExpiresAt":{"type":"string","format":"date-time","description":"Timestamp when the draft version expires."},"logging":{"type":"object","description":"Flow-level logging configuration.","properties":{"mode":{"type":"string","description":"Logging verbosity level.","enum":["accountLevel","basic","detailed"]},"debugUntil":{"type":"string","format":"date-time","description":"Temporary debug-level logging until this timestamp (max 1 hour from now)."}}},"numInstances":{"type":"integer","description":"Number of instance flows derived from this abstract flow.","readOnly":true},"preSave":{"type":"object","description":"Pre-save hook that runs a script before persisting flow changes.","properties":{"function":{"type":"string","description":"Function name to invoke."},"_scriptId":{"type":"string","format":"objectId","description":"Script containing the pre-save function."}}},"settingsForm":{"type":"object","description":"Form definition for collecting flow-level settings from users in the UI.","additionalProperties":true}}},"PageGenerator":{"type":"object","description":"A data source that produces pages of records for the flow. Page generators are the\nentry points of a flow; each references an export, can carry its own schedule, and\nmultiple generators can run in parallel when the flow enables it.","required":["_exportId"],"properties":{"_exportId":{"type":"string","format":"objectId","description":"Export that retrieves data from the source system. The server rejects page\ngenerator entries without a valid export reference."},"schedule":{"type":"string","description":"Cron expression for this specific generator, overriding the flow's main schedule.\nWhen omitted, the generator inherits the flow's schedule."},"skipRetries":{"type":"boolean","description":"When true, failed records from this generator are not retried — errors are logged\nand the flow continues. When false, failed records are retried per platform policy."},"setupInProgress":{"type":"boolean","description":"When true, the generator's configuration is still being set up in the UI and the step is not yet runnable."},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Coordinates delta timing so this generator's checkpoint stays behind the referenced\nflow, preventing child records from being processed before their parents."},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Like `_keepDeltaBehindFlowId` but targets a specific export's delta timestamp."},"__startDateHelper":{"type":"string","description":"Internal helper field for managing scheduled start dates."}}},"PageProcessor":{"type":"object","description":"A processing step that operates on pages of records within a flow. Processors are\neither lookups (`type: export`) that enrich records or imports (`type: import`) that\nwrite records to a destination, and execute sequentially unless routed into branches.","required":["type"],"properties":{"type":{"type":"string","description":"Selects whether this step runs a lookup export or an import, and which reference field applies.","enum":["export","import"]},"_exportId":{"type":"string","format":"objectId","description":"Lookup export that enriches incoming records. Required when `type` is `export`;\nthe referenced export must be configured as a lookup (`isLookup: true`)."},"_importId":{"type":"string","format":"objectId","description":"Import that writes records to the destination system. Required when `type` is `import`."},"proceedOnFailure":{"type":"boolean","description":"When true, records that fail in this processor continue to subsequent steps and the\nerror is logged. When false, failed records stop at this step."},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"hooks":{"type":"object","description":"Custom code hooks extending this processor's behavior.","properties":{"postResponseMap":{"type":"object","description":"Hook that runs after the step's response mapping completes.","properties":{"function":{"type":"string","description":"Function to invoke within the referenced script."},"_scriptId":{"type":"string","format":"objectId","description":"Script containing the hook function named in `function`."}}}}},"setupInProgress":{"type":"boolean","description":"When true, the processor's configuration is still being set up in the UI and the step is not yet runnable."}},"if":{"properties":{"type":{"const":"export"}},"required":["type"]},"then":{"required":["_exportId"]},"else":{"if":{"properties":{"type":{"const":"import"}},"required":["type"]},"then":{"required":["_importId"]}}},"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":"When true, marks this entry as an internal identifier."}}}},"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":"When true, marks this entry as an internal identifier."}}}},"_id":{"type":"boolean","description":"When true, marks this entry as an internal identifier."}}}},"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.","enum":["first_matching_branch","all_matching_branches"],"default":"first_matching_branch"},"routeRecordsUsing":{"type":"string","description":"Method used to evaluate routing criteria.","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","description":"Version of the filter expression format used by the rules; currently only \"1\" is supported."},"rules":{"type":"object","additionalProperties":true,"description":"Filter expression defining the matching criteria, in prefix notation — the operator first, followed by its operands, which may be nested expressions."}}},"groupByFields":{"type":"array","description":"Override grouping fields","items":{"type":"string"}},"test":{"type":"object","description":"Override test mode settings","properties":{"limit":{"type":"integer","description":"Overrides the test-mode record cap on the abstract flow's export — the total number of records a test run processes."}}},"delta":{"type":"object","description":"Override delta configuration","properties":{"dateField":{"type":"string","description":"Overrides the delta date field on the abstract flow's export — the record timestamp field(s) compared against the last successful run time to identify changed records. Accepts a single field or multiple comma-separated fields."},"dateFormat":{"type":"string","description":"Overrides the moment.js format string applied to the delta cutoff timestamp; ISO 8601 is used when unset."},"startDate":{"type":"string","description":"Overrides the fixed start timestamp used for the delta window on the abstract flow's export, in place of the last successful run time."},"lagOffset":{"type":"integer","description":"Overrides the buffer in milliseconds subtracted from the last successful run timestamp, creating an overlapping window that catches late-propagating records."},"endDateField":{"type":"string","description":"Overrides the record timestamp field used as the upper bound of the delta window on the abstract flow's export."}}},"once":{"type":"object","description":"Override once export settings","properties":{"booleanField":{"type":"string","description":"Overrides the once-mode tracking field on the abstract flow's export — the boolean field in the source system that is false for unprocessed records and set to true after successful processing."}}},"valueDelta":{"type":"object","description":"Override value delta settings","properties":{"exportedField":{"type":"string","description":"Overrides the field that tracks the last exported value on the abstract flow's export."},"pendingField":{"type":"string","description":"Overrides the field that tracks the pending (not yet exported) value on the abstract flow's export."}}},"webhook":{"type":"object","description":"Override webhook configuration","properties":{"token_crypt":{"type":"string","description":"Encrypted form of the webhook verification token, stored at rest."},"token_salt":{"type":"string","description":"Salt used to encrypt the corresponding webhook token."},"path":{"type":"string","description":"Overrides the location of the verification token on the abstract flow's webhook export — a JSON path into the request body or a query parameter name."},"key_crypt":{"type":"string","description":"Encrypted form of the webhook HMAC or public key, stored at rest."},"key_salt":{"type":"string","description":"Salt used to encrypt the corresponding webhook key."},"header":{"type":"string","description":"Overrides the name of the request header that carries the HMAC signature on the abstract flow's webhook export."},"username":{"type":"string","description":"Overrides the username used for basic-auth webhook verification on the abstract flow's export."},"password_crypt":{"type":"string","description":"Encrypted form of the basic-auth webhook password, stored at rest."},"password_salt":{"type":"string","description":"Salt used to encrypt the corresponding webhook password."},"successStatusCode":{"type":"integer","description":"Overrides the HTTP status code returned to the webhook caller after successful processing."},"successBody":{"type":"string","description":"Overrides the response body returned to the webhook caller after successful processing; ignored when the status code is 204."},"successMediaType":{"type":"string","description":"Overrides the Content-Type of successful webhook responses; must match the format of the success body."}}},"distributed":{"type":"object","description":"Override distributed processing settings","properties":{"bearerToken_crypt":{"type":"string","description":"Encrypted form of the distributed export's bearer token, stored at rest."},"bearerToken_salt":{"type":"string","description":"Salt used to encrypt the corresponding bearer token."}}},"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","description":"Overrides the ID lock template on the abstract flow's import — a handlebars template that generates a lock key so records resolving to the same key are not submitted concurrently."},"dataURITemplate":{"type":"string","description":"Overrides the data URI template on the abstract flow's import — a handlebars template that builds a link back to each record in the destination application's UI for error tracking."},"pathToMany":{"type":"string","description":"Overrides the one-to-many path on the abstract flow's import — the JSON path to child records within each parent record."},"blobKeyPath":{"type":"string","description":"Overrides the blob key path on the abstract flow's import — the path in the input record that holds the blob key identifying file content to import."},"filter":{"type":"object","additionalProperties":true,"description":"Overrides the filter on the abstract flow's import, which selects which incoming records are sent to the destination system."},"traceKeyTemplate":{"type":"string","description":"Overrides the trace key template on the abstract flow's import — a handlebars template controlling how each record's unique trace key is generated."},"parsers":{"type":"array","items":{"type":"object"},"description":"Overrides the parser configurations on the abstract flow's import."},"hooks":{"type":"object","additionalProperties":true,"description":"Overrides the hook configurations on the abstract flow's import — custom JavaScript hooks that run at fixed points in the import lifecycle."},"responseTransform":{"type":"object","additionalProperties":true,"description":"Overrides the response transform on the abstract flow's import, which reshapes the destination system's response after records are imported."},"mapping":{"type":"object","additionalProperties":true,"description":"Overrides the Mapper 1.0 mapping configuration on the abstract flow's import."},"mappings":{"type":"array","items":{"type":"object"},"description":"Overrides the Mapper 2.0 field mappings on the abstract flow's import, which transform incoming records into the destination system's field structure."},"lookups":{"type":"array","items":{"type":"object"},"description":"Overrides the lookup definitions on the abstract flow's import, referenced by its field mappings."},"settingsForm":{"type":"object","additionalProperties":true,"description":"Overrides the settings form definition on the abstract flow's import, which prompts users for values stored in `settings`."},"preSave":{"type":"object","additionalProperties":true,"description":"Overrides the preSave hook on the abstract flow's import — a JavaScript hook that executes before the resource is saved."},"settings":{"type":"object","additionalProperties":true,"description":"Overrides the custom settings on the abstract flow's import, accessible to hooks, filters, mappings, and handlebars templates at runtime."}}}},"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","description":"Reference to the script resource containing the routing logic used in place of the abstract router's script."},"function":{"type":"string","description":"Function name within the script that returns the branch name for each record."}}},"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":"Overrides the branch's display name within the router."},"description":{"type":"string","description":"Overrides the branch's description explaining its purpose and criteria."},"inputFilter":{"type":"object","description":"Overrides the branch's input filter — the criteria that determine which records are routed to this branch.","properties":{"version":{"type":"string","description":"Version of the filter expression format used by the rules; currently only \"1\" is supported."},"rules":{"type":"object","additionalProperties":true,"description":"Filter expression defining the branch's matching criteria, in prefix notation — the operator first, followed by its operands."}}}}}}}}}}},"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"}}}}}}}}}},"AIDescription":{"type":"object","description":"AI-generated descriptions and documentation for the resource.\n\nThis object contains automatically generated content that helps users\nunderstand the purpose, behavior, and configuration of the resource without\nrequiring them to analyze the technical details. The AI-generated content\nis sanitized and safe for display in the UI.\n","properties":{"summary":{"type":["string","null"],"description":"Brief AI-generated summary of the resource's purpose and functionality.\n\nThis concise description provides a quick overview of what the resource does,\nwhat systems it interacts with, and its primary role in the integration.\nThe summary is suitable for display in list views, dashboards, and other\ncontexts where space is limited.\n\nMaximum length: 10KB\n"},"detailed":{"type":["string","null"],"description":"Comprehensive AI-generated description of the resource's functionality.\n\nThis detailed explanation covers the resource's purpose, configuration details,\ndata flow patterns, filtering logic, and other technical aspects. It provides\nin-depth information suitable for documentation, tooltips, or detailed views\nin the administration interface.\n\nThe content may include HTML formatting for improved readability.\n\nMaximum length: 10KB\n"},"generatedOn":{"type":["string","null"],"format":"date-time","description":"Timestamp indicating when the AI description was generated.\n\nThis field helps track the freshness of the AI-generated content and\ndetermine when it might need to be regenerated due to changes in the\nresource's configuration or behavior.\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix).\n"}}},"ResourceResponse":{"type":"object","description":"Response","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the resource. Format is a 24-character hexadecimal string."},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was created. Set automatically and cannot be modified."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was last updated. Changes whenever any property is modified."},"deletedAt":{"type":["string","null"],"format":"date-time","readOnly":true,"description":"Timestamp when the resource was soft-deleted. When null or absent, the resource is active."}}},"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 flow, including its page generators, processors,\nrouters, schedule, and all nested settings.\n\nWalk `pageGenerators[]._exportId` and `pageProcessors[]._importId` (or\n`routers[].branches[].pageProcessors[]`) to discover the exports and imports wired into\nthe flow. For the full resource objects, use `GET /v1/flows/{_id}/descendants` instead of\nfetching each one individually. Instance flows (`_abstractFlowId` is set) have sparse\ntop-level fields because the runtime merges them with the abstract flow's config.","operationId":"getFlowById","tags":["Flows"],"parameters":[{"name":"_id","in":"path","description":"Flow id.","required":true,"schema":{"type":"string","format":"objectId"}},{"name":"mergeInstance","in":"query","description":"When true and the flow is an instance of an abstract (multi-instance) flow,\nthe response merges the abstract flow's configuration into the instance.\nWithout this, instance flows return a sparse object containing only\n`_abstractFlowId`, `overrides`, and instance-level fields — no\n`pageGenerators` or `routers`.","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Flow retrieved successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Flow"}}}},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## Update a flow

> Replaces the entire flow configuration. All fields not included in the request body are\
> reset to defaults — this is a full replace, not a merge.\
> \
> Always \`GET\` the flow first, modify the response, and \`PUT\` back — sending a partial body\
> erases omitted fields. To change a single field (e.g. \`disabled\`, \`schedule\`), prefer\
> \`PATCH\` over \`PUT\`. Read-only fields (\`\_id\`, \`createdAt\`, \`lastModified\`) in the request\
> body are silently ignored.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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 for creating or updating a flow.\n\nUse `pageProcessors` for simple linear flows or `routers` for conditional branching — never\ninclude both. The `schedule` field uses Celigo's 6-field cron format (not standard 5-field),\nwhere hours must be explicit comma-separated lists.","required":["name"],"allOf":[{"$ref":"#/components/schemas/FlowBase"}]},"FlowBase":{"type":"object","description":"Writable flow fields shared by the request and response schemas.\n\nUse `pageProcessors` for simple linear flows or `routers` for conditional branching — never\ninclude both. The `schedule` field uses Celigo's 6-field cron format (not standard 5-field),\nwhere hours must be explicit comma-separated lists.","properties":{"name":{"type":"string","maxLength":150,"description":"Display name for the flow."},"description":{"type":"string","maxLength":5120,"description":"Free-text description of the flow's purpose."},"_integrationId":{"type":["string","null"],"format":"objectId","description":"Integration this flow belongs to."},"schedule":{"type":["string","null"],"description":"Celigo 6-field cron expression: `? minute hour day-of-month month day-of-week`.\nHours must be explicit comma-separated lists (not `*/4` or `*`). Leave empty for\nevent-driven or webhook-triggered flows."},"timezone":{"type":["string","null"],"description":"IANA timezone for the schedule (e.g. `America/New_York`). Defaults to UTC."},"disabled":{"type":"boolean","description":"When true, scheduled executions are suspended and the flow cannot be triggered.\nRunning jobs are allowed to complete.","default":false},"pageGenerators":{"type":"array","description":"Data sources (exports) that produce pages of records for the flow. Mutually exclusive with\ntop-level `pageProcessors` when `routers` is used.","items":{"$ref":"#/components/schemas/PageGenerator"}},"pageProcessors":{"type":"array","description":"Sequential processing steps (imports, lookups, routers). Mutually exclusive with `routers` —\nuse one or the other, not both.","items":{"$ref":"#/components/schemas/PageProcessor"}},"routers":{"type":"array","description":"Routing configurations that direct records to conditional branches. Mutually exclusive with\ntop-level `pageProcessors` — use one or the other, not both.","items":{"$ref":"#/components/schemas/Router"}},"_runNextFlowIds":{"type":"array","description":"Flow IDs to trigger after this flow completes successfully.","items":{"type":"string","format":"objectId"}},"_runNextExportIds":{"type":"array","description":"Specific exports in other flows to trigger after completion.","items":{"type":"object","properties":{"_flowId":{"type":"string","format":"objectId","description":"Flow containing the export to trigger."},"_exportId":{"type":"string","format":"objectId","description":"Export to execute."}}}},"externalId":{"type":["string","null"],"description":"External identifier for correlating the flow with a record in another system."},"wizardState":{"type":"string","enum":["step2","step3","done"],"description":"Tracks how far the user has progressed through the flow setup wizard in the UI."},"settings":{"type":"object","description":"Custom key-value settings passed to hooks and scripts at runtime.","additionalProperties":true},"_connectorId":{"type":"string","format":"objectId","description":"Connector template this flow was created from."},"runPageGeneratorsInParallel":{"type":"boolean","description":"When true, all page generators start simultaneously instead of sequentially."},"autoResolveMatchingTraceKeys":{"type":"boolean","description":"When true, new errors with trace keys matching existing open errors are auto-resolved."},"isAbstract":{"type":"boolean","description":"Marks this as an abstract (multi-instance) flow — a reusable template that cannot be\nexecuted directly. Instance flows reference it via `_abstractFlowId` and provide `overrides`.\n\nConstraints: top-level `pageProcessors` are not allowed (use `routers`), cannot reference\nanother abstract flow, cannot be a \"run next\" target, and cannot be unset while instances exist."},"_abstractFlowId":{"type":"string","format":"objectId","description":"Abstract flow this instance inherits from. Immutable once set. The instance inherits\nthe flow graph and uses `overrides` to customize connections, schedules, and hooks."},"overrides":{"$ref":"#/components/schemas/Overrides"},"overridesHelper":{"$ref":"#/components/schemas/OverridesHelper"},"hidden":{"type":"boolean","description":"When true, the flow is hidden from standard UI views but remains executable via API."},"_flowGroupingId":{"type":["string","null"],"format":"objectId","description":"Flow grouping for organizing related flows in the UI. References an entry in the\nintegration's `flowGroupings` array (not a standalone collection); invalid ids are\nsilently dropped by the server."},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Coordinates delta timing so this flow's checkpoint stays behind the referenced flow.\nUsed for parent-child data relationships where the parent must sync first."},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Like `_keepDeltaBehindFlowId` but targets a specific export within a flow."},"aiDescription":{"$ref":"#/components/schemas/AIDescription"},"aliases":{"type":"array","description":"Named aliases that map to specific resources within the flow.","items":{"type":"object","properties":{"alias":{"type":"string","description":"Alias name."},"_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":"When true, this flow is in draft mode and not yet published."},"draftExpiresAt":{"type":"string","format":"date-time","description":"Timestamp when the draft version expires."},"logging":{"type":"object","description":"Flow-level logging configuration.","properties":{"mode":{"type":"string","description":"Logging verbosity level.","enum":["accountLevel","basic","detailed"]},"debugUntil":{"type":"string","format":"date-time","description":"Temporary debug-level logging until this timestamp (max 1 hour from now)."}}},"numInstances":{"type":"integer","description":"Number of instance flows derived from this abstract flow.","readOnly":true},"preSave":{"type":"object","description":"Pre-save hook that runs a script before persisting flow changes.","properties":{"function":{"type":"string","description":"Function name to invoke."},"_scriptId":{"type":"string","format":"objectId","description":"Script containing the pre-save function."}}},"settingsForm":{"type":"object","description":"Form definition for collecting flow-level settings from users in the UI.","additionalProperties":true}}},"PageGenerator":{"type":"object","description":"A data source that produces pages of records for the flow. Page generators are the\nentry points of a flow; each references an export, can carry its own schedule, and\nmultiple generators can run in parallel when the flow enables it.","required":["_exportId"],"properties":{"_exportId":{"type":"string","format":"objectId","description":"Export that retrieves data from the source system. The server rejects page\ngenerator entries without a valid export reference."},"schedule":{"type":"string","description":"Cron expression for this specific generator, overriding the flow's main schedule.\nWhen omitted, the generator inherits the flow's schedule."},"skipRetries":{"type":"boolean","description":"When true, failed records from this generator are not retried — errors are logged\nand the flow continues. When false, failed records are retried per platform policy."},"setupInProgress":{"type":"boolean","description":"When true, the generator's configuration is still being set up in the UI and the step is not yet runnable."},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Coordinates delta timing so this generator's checkpoint stays behind the referenced\nflow, preventing child records from being processed before their parents."},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Like `_keepDeltaBehindFlowId` but targets a specific export's delta timestamp."},"__startDateHelper":{"type":"string","description":"Internal helper field for managing scheduled start dates."}}},"PageProcessor":{"type":"object","description":"A processing step that operates on pages of records within a flow. Processors are\neither lookups (`type: export`) that enrich records or imports (`type: import`) that\nwrite records to a destination, and execute sequentially unless routed into branches.","required":["type"],"properties":{"type":{"type":"string","description":"Selects whether this step runs a lookup export or an import, and which reference field applies.","enum":["export","import"]},"_exportId":{"type":"string","format":"objectId","description":"Lookup export that enriches incoming records. Required when `type` is `export`;\nthe referenced export must be configured as a lookup (`isLookup: true`)."},"_importId":{"type":"string","format":"objectId","description":"Import that writes records to the destination system. Required when `type` is `import`."},"proceedOnFailure":{"type":"boolean","description":"When true, records that fail in this processor continue to subsequent steps and the\nerror is logged. When false, failed records stop at this step."},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"hooks":{"type":"object","description":"Custom code hooks extending this processor's behavior.","properties":{"postResponseMap":{"type":"object","description":"Hook that runs after the step's response mapping completes.","properties":{"function":{"type":"string","description":"Function to invoke within the referenced script."},"_scriptId":{"type":"string","format":"objectId","description":"Script containing the hook function named in `function`."}}}}},"setupInProgress":{"type":"boolean","description":"When true, the processor's configuration is still being set up in the UI and the step is not yet runnable."}},"if":{"properties":{"type":{"const":"export"}},"required":["type"]},"then":{"required":["_exportId"]},"else":{"if":{"properties":{"type":{"const":"import"}},"required":["type"]},"then":{"required":["_importId"]}}},"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":"When true, marks this entry as an internal identifier."}}}},"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":"When true, marks this entry as an internal identifier."}}}},"_id":{"type":"boolean","description":"When true, marks this entry as an internal identifier."}}}},"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.","enum":["first_matching_branch","all_matching_branches"],"default":"first_matching_branch"},"routeRecordsUsing":{"type":"string","description":"Method used to evaluate routing criteria.","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","description":"Version of the filter expression format used by the rules; currently only \"1\" is supported."},"rules":{"type":"object","additionalProperties":true,"description":"Filter expression defining the matching criteria, in prefix notation — the operator first, followed by its operands, which may be nested expressions."}}},"groupByFields":{"type":"array","description":"Override grouping fields","items":{"type":"string"}},"test":{"type":"object","description":"Override test mode settings","properties":{"limit":{"type":"integer","description":"Overrides the test-mode record cap on the abstract flow's export — the total number of records a test run processes."}}},"delta":{"type":"object","description":"Override delta configuration","properties":{"dateField":{"type":"string","description":"Overrides the delta date field on the abstract flow's export — the record timestamp field(s) compared against the last successful run time to identify changed records. Accepts a single field or multiple comma-separated fields."},"dateFormat":{"type":"string","description":"Overrides the moment.js format string applied to the delta cutoff timestamp; ISO 8601 is used when unset."},"startDate":{"type":"string","description":"Overrides the fixed start timestamp used for the delta window on the abstract flow's export, in place of the last successful run time."},"lagOffset":{"type":"integer","description":"Overrides the buffer in milliseconds subtracted from the last successful run timestamp, creating an overlapping window that catches late-propagating records."},"endDateField":{"type":"string","description":"Overrides the record timestamp field used as the upper bound of the delta window on the abstract flow's export."}}},"once":{"type":"object","description":"Override once export settings","properties":{"booleanField":{"type":"string","description":"Overrides the once-mode tracking field on the abstract flow's export — the boolean field in the source system that is false for unprocessed records and set to true after successful processing."}}},"valueDelta":{"type":"object","description":"Override value delta settings","properties":{"exportedField":{"type":"string","description":"Overrides the field that tracks the last exported value on the abstract flow's export."},"pendingField":{"type":"string","description":"Overrides the field that tracks the pending (not yet exported) value on the abstract flow's export."}}},"webhook":{"type":"object","description":"Override webhook configuration","properties":{"token_crypt":{"type":"string","description":"Encrypted form of the webhook verification token, stored at rest."},"token_salt":{"type":"string","description":"Salt used to encrypt the corresponding webhook token."},"path":{"type":"string","description":"Overrides the location of the verification token on the abstract flow's webhook export — a JSON path into the request body or a query parameter name."},"key_crypt":{"type":"string","description":"Encrypted form of the webhook HMAC or public key, stored at rest."},"key_salt":{"type":"string","description":"Salt used to encrypt the corresponding webhook key."},"header":{"type":"string","description":"Overrides the name of the request header that carries the HMAC signature on the abstract flow's webhook export."},"username":{"type":"string","description":"Overrides the username used for basic-auth webhook verification on the abstract flow's export."},"password_crypt":{"type":"string","description":"Encrypted form of the basic-auth webhook password, stored at rest."},"password_salt":{"type":"string","description":"Salt used to encrypt the corresponding webhook password."},"successStatusCode":{"type":"integer","description":"Overrides the HTTP status code returned to the webhook caller after successful processing."},"successBody":{"type":"string","description":"Overrides the response body returned to the webhook caller after successful processing; ignored when the status code is 204."},"successMediaType":{"type":"string","description":"Overrides the Content-Type of successful webhook responses; must match the format of the success body."}}},"distributed":{"type":"object","description":"Override distributed processing settings","properties":{"bearerToken_crypt":{"type":"string","description":"Encrypted form of the distributed export's bearer token, stored at rest."},"bearerToken_salt":{"type":"string","description":"Salt used to encrypt the corresponding bearer token."}}},"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","description":"Overrides the ID lock template on the abstract flow's import — a handlebars template that generates a lock key so records resolving to the same key are not submitted concurrently."},"dataURITemplate":{"type":"string","description":"Overrides the data URI template on the abstract flow's import — a handlebars template that builds a link back to each record in the destination application's UI for error tracking."},"pathToMany":{"type":"string","description":"Overrides the one-to-many path on the abstract flow's import — the JSON path to child records within each parent record."},"blobKeyPath":{"type":"string","description":"Overrides the blob key path on the abstract flow's import — the path in the input record that holds the blob key identifying file content to import."},"filter":{"type":"object","additionalProperties":true,"description":"Overrides the filter on the abstract flow's import, which selects which incoming records are sent to the destination system."},"traceKeyTemplate":{"type":"string","description":"Overrides the trace key template on the abstract flow's import — a handlebars template controlling how each record's unique trace key is generated."},"parsers":{"type":"array","items":{"type":"object"},"description":"Overrides the parser configurations on the abstract flow's import."},"hooks":{"type":"object","additionalProperties":true,"description":"Overrides the hook configurations on the abstract flow's import — custom JavaScript hooks that run at fixed points in the import lifecycle."},"responseTransform":{"type":"object","additionalProperties":true,"description":"Overrides the response transform on the abstract flow's import, which reshapes the destination system's response after records are imported."},"mapping":{"type":"object","additionalProperties":true,"description":"Overrides the Mapper 1.0 mapping configuration on the abstract flow's import."},"mappings":{"type":"array","items":{"type":"object"},"description":"Overrides the Mapper 2.0 field mappings on the abstract flow's import, which transform incoming records into the destination system's field structure."},"lookups":{"type":"array","items":{"type":"object"},"description":"Overrides the lookup definitions on the abstract flow's import, referenced by its field mappings."},"settingsForm":{"type":"object","additionalProperties":true,"description":"Overrides the settings form definition on the abstract flow's import, which prompts users for values stored in `settings`."},"preSave":{"type":"object","additionalProperties":true,"description":"Overrides the preSave hook on the abstract flow's import — a JavaScript hook that executes before the resource is saved."},"settings":{"type":"object","additionalProperties":true,"description":"Overrides the custom settings on the abstract flow's import, accessible to hooks, filters, mappings, and handlebars templates at runtime."}}}},"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","description":"Reference to the script resource containing the routing logic used in place of the abstract router's script."},"function":{"type":"string","description":"Function name within the script that returns the branch name for each record."}}},"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":"Overrides the branch's display name within the router."},"description":{"type":"string","description":"Overrides the branch's description explaining its purpose and criteria."},"inputFilter":{"type":"object","description":"Overrides the branch's input filter — the criteria that determine which records are routed to this branch.","properties":{"version":{"type":"string","description":"Version of the filter expression format used by the rules; currently only \"1\" is supported."},"rules":{"type":"object","additionalProperties":true,"description":"Filter expression defining the branch's matching criteria, in prefix notation — the operator first, followed by its operands."}}}}}}}}}}},"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"}}}}}}}}}},"AIDescription":{"type":"object","description":"AI-generated descriptions and documentation for the resource.\n\nThis object contains automatically generated content that helps users\nunderstand the purpose, behavior, and configuration of the resource without\nrequiring them to analyze the technical details. The AI-generated content\nis sanitized and safe for display in the UI.\n","properties":{"summary":{"type":["string","null"],"description":"Brief AI-generated summary of the resource's purpose and functionality.\n\nThis concise description provides a quick overview of what the resource does,\nwhat systems it interacts with, and its primary role in the integration.\nThe summary is suitable for display in list views, dashboards, and other\ncontexts where space is limited.\n\nMaximum length: 10KB\n"},"detailed":{"type":["string","null"],"description":"Comprehensive AI-generated description of the resource's functionality.\n\nThis detailed explanation covers the resource's purpose, configuration details,\ndata flow patterns, filtering logic, and other technical aspects. It provides\nin-depth information suitable for documentation, tooltips, or detailed views\nin the administration interface.\n\nThe content may include HTML formatting for improved readability.\n\nMaximum length: 10KB\n"},"generatedOn":{"type":["string","null"],"format":"date-time","description":"Timestamp indicating when the AI description was generated.\n\nThis field helps track the freshness of the AI-generated content and\ndetermine when it might need to be regenerated due to changes in the\nresource's configuration or behavior.\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix).\n"}}},"Flow":{"type":"object","required":["_id","name","disabled","logging","createdAt","lastModified"],"description":"Flow object as returned by the API.","allOf":[{"$ref":"#/components/schemas/FlowBase"},{"$ref":"#/components/schemas/ResourceResponse"},{"type":"object","properties":{"lastExecutedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp of the flow's most recent execution. Absent until the flow has run at least once."},"resolvedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow's open errors were last resolved."},"free":{"type":"boolean","readOnly":true,"description":"When true, the flow is free to run and does not require a paid subscription."},"_templateId":{"type":"string","format":"objectId","readOnly":true,"description":"Template this flow was created from."},"_sourceId":{"type":"string","format":"objectId","readOnly":true,"description":"Source resource this flow was cloned or installed from."}}}]},"ResourceResponse":{"type":"object","description":"Response","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the resource. Format is a 24-character hexadecimal string."},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was created. Set automatically and cannot be modified."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was last updated. Changes whenever any property is modified."},"deletedAt":{"type":["string","null"],"format":"date-time","readOnly":true,"description":"Timestamp when the resource was soft-deleted. When null or absent, the resource is active."}}},"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":"Replaces the entire flow configuration. All fields not included in the request body are\nreset to defaults — this is a full replace, not a merge.\n\nAlways `GET` the flow first, modify the response, and `PUT` back — sending a partial body\nerases omitted fields. To change a single field (e.g. `disabled`, `schedule`), prefer\n`PATCH` over `PUT`. Read-only fields (`_id`, `createdAt`, `lastModified`) in the request\nbody are silently ignored.","operationId":"updateFlow","tags":["Flows"],"parameters":[{"name":"_id","in":"path","description":"Flow id.","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/Flow"}}}},"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. Soft-deleted and retained in the recycle bin for 30 days.\
> Scheduled executions are stopped and any running jobs are cancelled.\
> \
> Check \`GET /v1/flows/{\_id}/dependencies\` first — if other resources reference this flow,\
> the delete is blocked. Soft-deleted flows can be restored via the recycle bin endpoints\
> within 30 days.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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"}}}},"422-dependency-conflict":{"description":"The resource has dependents that must be deleted first. Each entry\nin the `errors` array names one blocking resource.","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. Soft-deleted and retained in the recycle bin for 30 days.\nScheduled executions are stopped and any running jobs are cancelled.\n\nCheck `GET /v1/flows/{_id}/dependencies` first — if other resources reference this flow,\nthe delete is blocked. Soft-deleted flows can be restored via the recycle bin endpoints\nwithin 30 days.","operationId":"deleteFlow","tags":["Flows"],"parameters":[{"name":"_id","in":"path","description":"Flow id.","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"},"422":{"$ref":"#/components/responses/422-dependency-conflict"}}}}}}
```

## 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 |\
> \| \`/logging/debugUntil\` | Debug logging expiry (ISO-8601, max 1 hour from now) |\
> \| \`/logging/mode\` | Logging mode |\
> \| \`/runPageGeneratorsInParallel\` | Run page generators in parallel |\
> \| \`/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.\
> \
> PATCH is safer than PUT for toggling \`disabled\` or arming debug logging because it won't\
> accidentally reset other fields. To arm debug logging, \`replace\` \`/logging/debugUntil\` with\
> an ISO timestamp up to 1 hour in the future; to disarm, set it to a past timestamp or null.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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 on whitelisted fields — all other paths are rejected\nwith 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","add","remove"],"description":"The operation to perform."},"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. Required for `replace` and `add`, omit for `remove`."}}},"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 |\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 |\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.\n\nPATCH is safer than PUT for toggling `disabled` or arming debug logging because it won't\naccidentally reset other fields. To arm debug logging, `replace` `/logging/debugUntil` with\nan ISO timestamp up to 1 hour in the future; to disarm, set it to a past timestamp or null.","operationId":"patchFlow","tags":["Flows"],"parameters":[{"name":"_id","in":"path","description":"Flow id.","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 a flow along with all transitive dependencies (exports, imports, scripts).\
> \`\_integrationId\` is required, and \`connectionMap\` is required when the flow references\
> connections — map a connection id to itself to reuse it, or to a different id to remap.\
> \
> Use \`GET /v1/flows/{\_id}/clone/preview\` first to see what resources will be created and\
> which connections need remapping. The cloned flow is always created \`disabled: true\`.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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.","required":["_integrationId"],"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":"Integration to attach the cloned flow to. The server rejects clones without it\n(`invalid_ref` \"Integration not found for the given id\")."},"connectionMap":{"type":"object","description":"Mapping of original connection ids to replacement connection ids. Keys are source\nconnection ids on the original resource; values are target connection ids. Required\nwhen the flow references connections — omitting it fails with 400\n`invalid_connectionMap`. Map a connection to itself to reuse it in the clone.","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/Flow"},{"title":"Resource manifest","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."}}}}]},"Flow":{"type":"object","required":["_id","name","disabled","logging","createdAt","lastModified"],"description":"Flow object as returned by the API.","allOf":[{"$ref":"#/components/schemas/FlowBase"},{"$ref":"#/components/schemas/ResourceResponse"},{"type":"object","properties":{"lastExecutedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp of the flow's most recent execution. Absent until the flow has run at least once."},"resolvedAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the flow's open errors were last resolved."},"free":{"type":"boolean","readOnly":true,"description":"When true, the flow is free to run and does not require a paid subscription."},"_templateId":{"type":"string","format":"objectId","readOnly":true,"description":"Template this flow was created from."},"_sourceId":{"type":"string","format":"objectId","readOnly":true,"description":"Source resource this flow was cloned or installed from."}}}]},"FlowBase":{"type":"object","description":"Writable flow fields shared by the request and response schemas.\n\nUse `pageProcessors` for simple linear flows or `routers` for conditional branching — never\ninclude both. The `schedule` field uses Celigo's 6-field cron format (not standard 5-field),\nwhere hours must be explicit comma-separated lists.","properties":{"name":{"type":"string","maxLength":150,"description":"Display name for the flow."},"description":{"type":"string","maxLength":5120,"description":"Free-text description of the flow's purpose."},"_integrationId":{"type":["string","null"],"format":"objectId","description":"Integration this flow belongs to."},"schedule":{"type":["string","null"],"description":"Celigo 6-field cron expression: `? minute hour day-of-month month day-of-week`.\nHours must be explicit comma-separated lists (not `*/4` or `*`). Leave empty for\nevent-driven or webhook-triggered flows."},"timezone":{"type":["string","null"],"description":"IANA timezone for the schedule (e.g. `America/New_York`). Defaults to UTC."},"disabled":{"type":"boolean","description":"When true, scheduled executions are suspended and the flow cannot be triggered.\nRunning jobs are allowed to complete.","default":false},"pageGenerators":{"type":"array","description":"Data sources (exports) that produce pages of records for the flow. Mutually exclusive with\ntop-level `pageProcessors` when `routers` is used.","items":{"$ref":"#/components/schemas/PageGenerator"}},"pageProcessors":{"type":"array","description":"Sequential processing steps (imports, lookups, routers). Mutually exclusive with `routers` —\nuse one or the other, not both.","items":{"$ref":"#/components/schemas/PageProcessor"}},"routers":{"type":"array","description":"Routing configurations that direct records to conditional branches. Mutually exclusive with\ntop-level `pageProcessors` — use one or the other, not both.","items":{"$ref":"#/components/schemas/Router"}},"_runNextFlowIds":{"type":"array","description":"Flow IDs to trigger after this flow completes successfully.","items":{"type":"string","format":"objectId"}},"_runNextExportIds":{"type":"array","description":"Specific exports in other flows to trigger after completion.","items":{"type":"object","properties":{"_flowId":{"type":"string","format":"objectId","description":"Flow containing the export to trigger."},"_exportId":{"type":"string","format":"objectId","description":"Export to execute."}}}},"externalId":{"type":["string","null"],"description":"External identifier for correlating the flow with a record in another system."},"wizardState":{"type":"string","enum":["step2","step3","done"],"description":"Tracks how far the user has progressed through the flow setup wizard in the UI."},"settings":{"type":"object","description":"Custom key-value settings passed to hooks and scripts at runtime.","additionalProperties":true},"_connectorId":{"type":"string","format":"objectId","description":"Connector template this flow was created from."},"runPageGeneratorsInParallel":{"type":"boolean","description":"When true, all page generators start simultaneously instead of sequentially."},"autoResolveMatchingTraceKeys":{"type":"boolean","description":"When true, new errors with trace keys matching existing open errors are auto-resolved."},"isAbstract":{"type":"boolean","description":"Marks this as an abstract (multi-instance) flow — a reusable template that cannot be\nexecuted directly. Instance flows reference it via `_abstractFlowId` and provide `overrides`.\n\nConstraints: top-level `pageProcessors` are not allowed (use `routers`), cannot reference\nanother abstract flow, cannot be a \"run next\" target, and cannot be unset while instances exist."},"_abstractFlowId":{"type":"string","format":"objectId","description":"Abstract flow this instance inherits from. Immutable once set. The instance inherits\nthe flow graph and uses `overrides` to customize connections, schedules, and hooks."},"overrides":{"$ref":"#/components/schemas/Overrides"},"overridesHelper":{"$ref":"#/components/schemas/OverridesHelper"},"hidden":{"type":"boolean","description":"When true, the flow is hidden from standard UI views but remains executable via API."},"_flowGroupingId":{"type":["string","null"],"format":"objectId","description":"Flow grouping for organizing related flows in the UI. References an entry in the\nintegration's `flowGroupings` array (not a standalone collection); invalid ids are\nsilently dropped by the server."},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Coordinates delta timing so this flow's checkpoint stays behind the referenced flow.\nUsed for parent-child data relationships where the parent must sync first."},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Like `_keepDeltaBehindFlowId` but targets a specific export within a flow."},"aiDescription":{"$ref":"#/components/schemas/AIDescription"},"aliases":{"type":"array","description":"Named aliases that map to specific resources within the flow.","items":{"type":"object","properties":{"alias":{"type":"string","description":"Alias name."},"_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":"When true, this flow is in draft mode and not yet published."},"draftExpiresAt":{"type":"string","format":"date-time","description":"Timestamp when the draft version expires."},"logging":{"type":"object","description":"Flow-level logging configuration.","properties":{"mode":{"type":"string","description":"Logging verbosity level.","enum":["accountLevel","basic","detailed"]},"debugUntil":{"type":"string","format":"date-time","description":"Temporary debug-level logging until this timestamp (max 1 hour from now)."}}},"numInstances":{"type":"integer","description":"Number of instance flows derived from this abstract flow.","readOnly":true},"preSave":{"type":"object","description":"Pre-save hook that runs a script before persisting flow changes.","properties":{"function":{"type":"string","description":"Function name to invoke."},"_scriptId":{"type":"string","format":"objectId","description":"Script containing the pre-save function."}}},"settingsForm":{"type":"object","description":"Form definition for collecting flow-level settings from users in the UI.","additionalProperties":true}}},"PageGenerator":{"type":"object","description":"A data source that produces pages of records for the flow. Page generators are the\nentry points of a flow; each references an export, can carry its own schedule, and\nmultiple generators can run in parallel when the flow enables it.","required":["_exportId"],"properties":{"_exportId":{"type":"string","format":"objectId","description":"Export that retrieves data from the source system. The server rejects page\ngenerator entries without a valid export reference."},"schedule":{"type":"string","description":"Cron expression for this specific generator, overriding the flow's main schedule.\nWhen omitted, the generator inherits the flow's schedule."},"skipRetries":{"type":"boolean","description":"When true, failed records from this generator are not retried — errors are logged\nand the flow continues. When false, failed records are retried per platform policy."},"setupInProgress":{"type":"boolean","description":"When true, the generator's configuration is still being set up in the UI and the step is not yet runnable."},"_keepDeltaBehindFlowId":{"type":"string","format":"objectId","description":"Coordinates delta timing so this generator's checkpoint stays behind the referenced\nflow, preventing child records from being processed before their parents."},"_keepDeltaBehindExportId":{"type":"string","format":"objectId","description":"Like `_keepDeltaBehindFlowId` but targets a specific export's delta timestamp."},"__startDateHelper":{"type":"string","description":"Internal helper field for managing scheduled start dates."}}},"PageProcessor":{"type":"object","description":"A processing step that operates on pages of records within a flow. Processors are\neither lookups (`type: export`) that enrich records or imports (`type: import`) that\nwrite records to a destination, and execute sequentially unless routed into branches.","required":["type"],"properties":{"type":{"type":"string","description":"Selects whether this step runs a lookup export or an import, and which reference field applies.","enum":["export","import"]},"_exportId":{"type":"string","format":"objectId","description":"Lookup export that enriches incoming records. Required when `type` is `export`;\nthe referenced export must be configured as a lookup (`isLookup: true`)."},"_importId":{"type":"string","format":"objectId","description":"Import that writes records to the destination system. Required when `type` is `import`."},"proceedOnFailure":{"type":"boolean","description":"When true, records that fail in this processor continue to subsequent steps and the\nerror is logged. When false, failed records stop at this step."},"responseMapping":{"$ref":"#/components/schemas/ResponseMapping"},"hooks":{"type":"object","description":"Custom code hooks extending this processor's behavior.","properties":{"postResponseMap":{"type":"object","description":"Hook that runs after the step's response mapping completes.","properties":{"function":{"type":"string","description":"Function to invoke within the referenced script."},"_scriptId":{"type":"string","format":"objectId","description":"Script containing the hook function named in `function`."}}}}},"setupInProgress":{"type":"boolean","description":"When true, the processor's configuration is still being set up in the UI and the step is not yet runnable."}},"if":{"properties":{"type":{"const":"export"}},"required":["type"]},"then":{"required":["_exportId"]},"else":{"if":{"properties":{"type":{"const":"import"}},"required":["type"]},"then":{"required":["_importId"]}}},"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":"When true, marks this entry as an internal identifier."}}}},"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":"When true, marks this entry as an internal identifier."}}}},"_id":{"type":"boolean","description":"When true, marks this entry as an internal identifier."}}}},"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.","enum":["first_matching_branch","all_matching_branches"],"default":"first_matching_branch"},"routeRecordsUsing":{"type":"string","description":"Method used to evaluate routing criteria.","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","description":"Version of the filter expression format used by the rules; currently only \"1\" is supported."},"rules":{"type":"object","additionalProperties":true,"description":"Filter expression defining the matching criteria, in prefix notation — the operator first, followed by its operands, which may be nested expressions."}}},"groupByFields":{"type":"array","description":"Override grouping fields","items":{"type":"string"}},"test":{"type":"object","description":"Override test mode settings","properties":{"limit":{"type":"integer","description":"Overrides the test-mode record cap on the abstract flow's export — the total number of records a test run processes."}}},"delta":{"type":"object","description":"Override delta configuration","properties":{"dateField":{"type":"string","description":"Overrides the delta date field on the abstract flow's export — the record timestamp field(s) compared against the last successful run time to identify changed records. Accepts a single field or multiple comma-separated fields."},"dateFormat":{"type":"string","description":"Overrides the moment.js format string applied to the delta cutoff timestamp; ISO 8601 is used when unset."},"startDate":{"type":"string","description":"Overrides the fixed start timestamp used for the delta window on the abstract flow's export, in place of the last successful run time."},"lagOffset":{"type":"integer","description":"Overrides the buffer in milliseconds subtracted from the last successful run timestamp, creating an overlapping window that catches late-propagating records."},"endDateField":{"type":"string","description":"Overrides the record timestamp field used as the upper bound of the delta window on the abstract flow's export."}}},"once":{"type":"object","description":"Override once export settings","properties":{"booleanField":{"type":"string","description":"Overrides the once-mode tracking field on the abstract flow's export — the boolean field in the source system that is false for unprocessed records and set to true after successful processing."}}},"valueDelta":{"type":"object","description":"Override value delta settings","properties":{"exportedField":{"type":"string","description":"Overrides the field that tracks the last exported value on the abstract flow's export."},"pendingField":{"type":"string","description":"Overrides the field that tracks the pending (not yet exported) value on the abstract flow's export."}}},"webhook":{"type":"object","description":"Override webhook configuration","properties":{"token_crypt":{"type":"string","description":"Encrypted form of the webhook verification token, stored at rest."},"token_salt":{"type":"string","description":"Salt used to encrypt the corresponding webhook token."},"path":{"type":"string","description":"Overrides the location of the verification token on the abstract flow's webhook export — a JSON path into the request body or a query parameter name."},"key_crypt":{"type":"string","description":"Encrypted form of the webhook HMAC or public key, stored at rest."},"key_salt":{"type":"string","description":"Salt used to encrypt the corresponding webhook key."},"header":{"type":"string","description":"Overrides the name of the request header that carries the HMAC signature on the abstract flow's webhook export."},"username":{"type":"string","description":"Overrides the username used for basic-auth webhook verification on the abstract flow's export."},"password_crypt":{"type":"string","description":"Encrypted form of the basic-auth webhook password, stored at rest."},"password_salt":{"type":"string","description":"Salt used to encrypt the corresponding webhook password."},"successStatusCode":{"type":"integer","description":"Overrides the HTTP status code returned to the webhook caller after successful processing."},"successBody":{"type":"string","description":"Overrides the response body returned to the webhook caller after successful processing; ignored when the status code is 204."},"successMediaType":{"type":"string","description":"Overrides the Content-Type of successful webhook responses; must match the format of the success body."}}},"distributed":{"type":"object","description":"Override distributed processing settings","properties":{"bearerToken_crypt":{"type":"string","description":"Encrypted form of the distributed export's bearer token, stored at rest."},"bearerToken_salt":{"type":"string","description":"Salt used to encrypt the corresponding bearer token."}}},"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","description":"Overrides the ID lock template on the abstract flow's import — a handlebars template that generates a lock key so records resolving to the same key are not submitted concurrently."},"dataURITemplate":{"type":"string","description":"Overrides the data URI template on the abstract flow's import — a handlebars template that builds a link back to each record in the destination application's UI for error tracking."},"pathToMany":{"type":"string","description":"Overrides the one-to-many path on the abstract flow's import — the JSON path to child records within each parent record."},"blobKeyPath":{"type":"string","description":"Overrides the blob key path on the abstract flow's import — the path in the input record that holds the blob key identifying file content to import."},"filter":{"type":"object","additionalProperties":true,"description":"Overrides the filter on the abstract flow's import, which selects which incoming records are sent to the destination system."},"traceKeyTemplate":{"type":"string","description":"Overrides the trace key template on the abstract flow's import — a handlebars template controlling how each record's unique trace key is generated."},"parsers":{"type":"array","items":{"type":"object"},"description":"Overrides the parser configurations on the abstract flow's import."},"hooks":{"type":"object","additionalProperties":true,"description":"Overrides the hook configurations on the abstract flow's import — custom JavaScript hooks that run at fixed points in the import lifecycle."},"responseTransform":{"type":"object","additionalProperties":true,"description":"Overrides the response transform on the abstract flow's import, which reshapes the destination system's response after records are imported."},"mapping":{"type":"object","additionalProperties":true,"description":"Overrides the Mapper 1.0 mapping configuration on the abstract flow's import."},"mappings":{"type":"array","items":{"type":"object"},"description":"Overrides the Mapper 2.0 field mappings on the abstract flow's import, which transform incoming records into the destination system's field structure."},"lookups":{"type":"array","items":{"type":"object"},"description":"Overrides the lookup definitions on the abstract flow's import, referenced by its field mappings."},"settingsForm":{"type":"object","additionalProperties":true,"description":"Overrides the settings form definition on the abstract flow's import, which prompts users for values stored in `settings`."},"preSave":{"type":"object","additionalProperties":true,"description":"Overrides the preSave hook on the abstract flow's import — a JavaScript hook that executes before the resource is saved."},"settings":{"type":"object","additionalProperties":true,"description":"Overrides the custom settings on the abstract flow's import, accessible to hooks, filters, mappings, and handlebars templates at runtime."}}}},"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","description":"Reference to the script resource containing the routing logic used in place of the abstract router's script."},"function":{"type":"string","description":"Function name within the script that returns the branch name for each record."}}},"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":"Overrides the branch's display name within the router."},"description":{"type":"string","description":"Overrides the branch's description explaining its purpose and criteria."},"inputFilter":{"type":"object","description":"Overrides the branch's input filter — the criteria that determine which records are routed to this branch.","properties":{"version":{"type":"string","description":"Version of the filter expression format used by the rules; currently only \"1\" is supported."},"rules":{"type":"object","additionalProperties":true,"description":"Filter expression defining the branch's matching criteria, in prefix notation — the operator first, followed by its operands."}}}}}}}}}}},"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"}}}}}}}}}},"AIDescription":{"type":"object","description":"AI-generated descriptions and documentation for the resource.\n\nThis object contains automatically generated content that helps users\nunderstand the purpose, behavior, and configuration of the resource without\nrequiring them to analyze the technical details. The AI-generated content\nis sanitized and safe for display in the UI.\n","properties":{"summary":{"type":["string","null"],"description":"Brief AI-generated summary of the resource's purpose and functionality.\n\nThis concise description provides a quick overview of what the resource does,\nwhat systems it interacts with, and its primary role in the integration.\nThe summary is suitable for display in list views, dashboards, and other\ncontexts where space is limited.\n\nMaximum length: 10KB\n"},"detailed":{"type":["string","null"],"description":"Comprehensive AI-generated description of the resource's functionality.\n\nThis detailed explanation covers the resource's purpose, configuration details,\ndata flow patterns, filtering logic, and other technical aspects. It provides\nin-depth information suitable for documentation, tooltips, or detailed views\nin the administration interface.\n\nThe content may include HTML formatting for improved readability.\n\nMaximum length: 10KB\n"},"generatedOn":{"type":["string","null"],"format":"date-time","description":"Timestamp indicating when the AI description was generated.\n\nThis field helps track the freshness of the AI-generated content and\ndetermine when it might need to be regenerated due to changes in the\nresource's configuration or behavior.\n\nThe timestamp is recorded in ISO 8601 format with UTC timezone (Z suffix).\n"}}},"ResourceResponse":{"type":"object","description":"Response","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the resource. Format is a 24-character hexadecimal string."},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was created. Set automatically and cannot be modified."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was last updated. Changes whenever any property is modified."},"deletedAt":{"type":["string","null"],"format":"date-time","readOnly":true,"description":"Timestamp when the resource was soft-deleted. When null or absent, the resource is active."}}},"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 a flow along with all transitive dependencies (exports, imports, scripts).\n`_integrationId` is required, and `connectionMap` is required when the flow references\nconnections — map a connection id to itself to reuse it, or to a different id to remap.\n\nUse `GET /v1/flows/{_id}/clone/preview` first to see what resources will be created and\nwhich connections need remapping. The cloned flow is always created `disabled: true`.","operationId":"cloneFlow","tags":["Flows"],"parameters":[{"name":"_id","in":"path","description":"Flow id 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 resources that would be created by cloning this flow — the target flow\
> and all transitive dependencies (connections, exports, imports, scripts, async helpers,\
> lookup caches). No resources are created.\
> \
> Call this before \`POST /v1/flows/{\_id}/clone\` to discover which connections need remapping\
> in the \`connectionMap\` body field.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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}}}},"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."}}},"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 resources that would be created by cloning this flow — the target flow\nand all transitive dependencies (connections, exports, imports, scripts, async helpers,\nlookup caches). No resources are created.\n\nCall this before `POST /v1/flows/{_id}/clone` to discover which connections need remapping\nin the `connectionMap` body field.","operationId":"previewCloneFlow","tags":["Flows"],"parameters":[{"name":"_id","in":"path","description":"Flow id 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.\
> \
> The returned arrays mirror the full resource shapes from \`GET /v1/imports/{\_id}\`,\
> \`GET /v1/exports/{\_id}\`, and \`GET /v1/tools/{\_id}\`.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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}}}},"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\nThe returned arrays mirror the full resource shapes from `GET /v1/imports/{_id}`,\n`GET /v1/exports/{_id}`, and `GET /v1/tools/{_id}`.","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.\
> \
> For the full list of error records on a single step, call\
> \`GET /v1/flows/{\_id}/{\_stepId}/errors\`. For a whole-integration rollup, use\
> \`GET /v1/integrations/{\_id}/errors\`. \`lastErrorAt\` is only populated on entries with\
> \`numError > 0\`.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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."}}}}}},"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\nFor the full list of error records on a single step, call\n`GET /v1/flows/{_id}/{_stepId}/errors`. For a whole-integration rollup, use\n`GET /v1/integrations/{_id}/errors`. `lastErrorAt` is only populated on entries with\n`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.\
> \
> Use \`GET /v1/flows/{\_id}/descendants\` to verify which resources use a given connection\
> before replacing.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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\nUse `GET /v1/flows/{_id}/descendants` to verify which resources use a given connection\nbefore replacing.","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).\
> \
> \
> To trace a run end-to-end, arm debug logging before calling this, then use the returned\
> \`\_jobId\` with the execution-log endpoints. For delta backfills, prefer passing explicit\
> \`startDate\`/\`endDate\` over editing the export's \`lastExportDateTime\` — the override is\
> scoped to one run. A 200 with \`\_jobId\` absent means the request was accepted but no job\
> was queued, usually because another run is already in progress.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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- **Single queued run** — an object with the parent job id (`_jobId`) plus queue metadata.\n- **On-demand / multi-export run** — an array of per-export run records.\n- **Rejected run** — an object with an `error` field. (Note: a run on a *disabled* flow is\n  rejected with HTTP 422 `invalid_flow`, not this shape.)\n\nCallers should branch on the response shape before treating it as a single job.","oneOf":[{"title":"single run","type":"object","additionalProperties":true,"required":["_jobId"],"description":"Single-job run result. Observed keys: `_jobId` (the parent job to poll), `_exportId`,\n`endDate`, `queueName`, and `message` (the internal queue payload — treat as opaque).","properties":{"_jobId":{"type":"string","format":"objectId","description":"Parent job id for the queued run; poll `GET /v1/jobs/{_id}` for status."}}},{"title":"per-export runs","type":"array","description":"Per-export run results for a multi-generator flow.","items":{"type":"object","additionalProperties":true}},{"title":"run rejected","type":"object","required":["error"],"description":"Run-rejected response.","properties":{"error":{"type":"string","description":"Human-readable reason the run was not started."}}}]},"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\nTo trace a run end-to-end, arm debug logging before calling this, then use the returned\n`_jobId` with the execution-log endpoints. For delta backfills, prefer passing explicit\n`startDate`/`endDate` over editing the export's `lastExportDateTime` — the override is\nscoped to one run. A 200 with `_jobId` absent means the request was accepted but no job\nwas queued, usually because another run is already in progress.","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.\
> \
> If both \`fields\` and \`templates\` are empty for a generator, the flow has no trace key configured\
> and log correlation must be done by position or other means. Trace keys are especially important\
> for fan-out flows where one source record produces many destination records.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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\nIf both `fields` and `templates` are empty for a generator, the flow has no trace key configured\nand log correlation must be done by position or other means. Trace keys are especially important\nfor fan-out flows where one source record produces many destination records.","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\`.\
> \
> A missing or very old value means the next delta run will re-scan the full history window from\
> the source. This is the flow-scoped checkpoint; per-export checkpoints (for flows with multiple\
> generators that advance independently) are exposed on the export record's \`delta\` block.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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."}}},"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\nA missing or very old value means the next delta run will re-scan the full history window from\nthe source. This is the flow-scoped checkpoint; per-export checkpoints (for flows with multiple\ngenerators that advance 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.\
> \
> Flow groupings are managed on the parent integration (\`PUT /v1/integrations/{\_id}\` with a\
> modified \`flowGroupings\[]\` array) — create the group first, then call this to populate it.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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\nFlow groupings are managed on the parent integration (`PUT /v1/integrations/{_id}` with a\nmodified `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. The server does not validate the grouping id —\nnonexistent `_flowGroupingId` values are also accepted with 204."},"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\[]\`.\
> \
> For a flow-wide rollup (per-step counts only), use \`GET /v1/flows/{\_id}/errors\` instead.\
> Filter client-side by \`\_flowJobId\` when you want errors from one specific run. Errors with a\
> \`retryDataKey\` are retryable via \`POST .../retry\`; connection-level errors typically lack one\
> and require a full flow rerun to recover.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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."}}},"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."},"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.\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."}}},"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\nFor a flow-wide rollup (per-step counts only), use `GET /v1/flows/{_id}/errors` instead.\nFilter client-side by `_flowJobId` when you want errors from one specific run. Errors with a\n`retryDataKey` are retryable via `POST .../retry`; connection-level errors typically lack one\nand require a full flow rerun to recover.","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.\
> \
> The \`email\` value is accepted verbatim and is not validated against the account's user list.\
> Re-assigning the same batch to a different user overwrites the prior assignment. Use\
> \`PUT .../errors/unassign\` to remove assignments entirely.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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"}}}},"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\nThe `email` value is accepted verbatim and is not validated against the account's user list.\nRe-assigning the same batch to a different user overwrites the prior assignment. Use\n`PUT .../errors/unassign` to remove assignments entirely.","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).\
> \
> The response's \`errorsToReturn\` contains only ids that were actually unassigned — ids that\
> were already unassigned or don't exist are omitted.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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"}}}},"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\nThe response's `errorsToReturn` contains only ids that were actually unassigned — ids that\nwere already unassigned or don't exist are omitted.","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\`.\
> \
> The signed URL requires no auth headers — do not attach your bearer token when fetching the CSV.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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."}}},"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\nThe signed URL requires no auth headers — do not attach your bearer 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 (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.\
> \
> \`resolvedBy\` distinguishes how each error was closed: \`auto\` means a system-initiated\
> auto-retry cleared it; a user ID means the error was resolved manually or via a\
> user-triggered retry.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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."}}},"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."},"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.\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."}}},"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 (same shape 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\n`resolvedBy` distinguishes how each error was closed: `auto` means a system-initiated\nauto-retry cleared it; a user ID means the error was resolved manually or via a\nuser-triggered 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"}}],"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.\
> \
> To actually re-run the failed records, use \`POST .../retry\` instead. The request body field\
> is named \`errors\` (carrying error ids), not \`errorIds\`.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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\nTo actually re-run the failed records, use `POST .../retry` instead. The request body field\nis named `errors` (carrying error ids), not `errorIds`.","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).\
> \
> Only resolved errors can be deleted through this endpoint — open errors must be resolved first.\
> This is destructive: the records and their associated HTTP request/response captures are\
> permanently removed. The request body field is named \`errors\` (carrying error ids).

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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\nOnly resolved errors can be deleted through this endpoint — open errors must be resolved first.\nThis is destructive: the records and their associated HTTP request/response captures are\npermanently removed. The request body field is named `errors` (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\`.\
> \
> For currently-open errors, use \`GET .../errors/signedURL\` instead.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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."}}},"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\nFor currently-open errors, use `GET .../errors/signedURL` instead.","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. System-initiated auto-retries set \`resolvedBy\` to \`"auto"\` instead.\
> \- 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\`.\
> \
> To modify a record before retrying, call \`GET .../{ retryDataKey}/data\`, mutate the payload,\
> \`PUT\` it back, then call this endpoint. Retried records go through the same page-processor\
> pipeline as new records with no ordering guarantees. Batch at 1000 keys per call.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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","required":["_id","type","status","createdAt","lastModified"],"description":"A job represents one execution of a flow/export/import (or a retry) in integrator.io.\nJobs are read-only records created by the platform when executions occur.\n\nParent jobs (`type: flow`) carry aggregate counters; child jobs (`type: export` or `import`)\ncarry per-step counters -- do not sum both to avoid double-counting. `_exportId` on a parent\nflow job references the page-generator export, not all exports in the flow.\n","allOf":[{"$ref":"#/components/schemas/ResourceResponse"},{"type":"object","properties":{"_userId":{"type":"string","format":"objectId","readOnly":true,"description":"Owner user id for the job."},"type":{"type":"string","readOnly":true,"description":"Job type.","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":"The export or import resource ID for this child job. Present on child\njobs (`type: export` or `type: import`) — check `type` to determine\nwhether this references an export or import resource."},"_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)."},"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's analytics data expires."},"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":"When true, all export pages have been generated."},"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":"When true, 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":{"description":"Error file artifact (if any).","allOf":[{"$ref":"#/components/schemas/JobErrorFileRef"},{"description":"Error file artifact (if any)."}]},"logMode":{"type":"string","readOnly":true,"description":"Effective logging mode for this job, resolved from the flow's `logging.mode`\nand the account-level logging preference. Common values: `basic` (default),\n`off`, `on`, `debug`."},"__lastPageGeneratorJob":{"type":"boolean","readOnly":true,"description":"When true, indicates the last page-generator job in the sequence. Internal use only."}}}]},"ResourceResponse":{"type":"object","description":"Response","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the resource. Format is a 24-character hexadecimal string."},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was created. Set automatically and cannot be modified."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was last updated. Changes whenever any property is modified."},"deletedAt":{"type":["string","null"],"format":"date-time","readOnly":true,"description":"Timestamp when the resource was soft-deleted. When null or absent, the resource is active."}}},"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. System-initiated auto-retries set `resolvedBy` to `\"auto\"` instead.\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\nTo modify a record before retrying, call `GET .../{ retryDataKey}/data`, mutate the payload,\n`PUT` it back, then call this endpoint. Retried records go through the same page-processor\npipeline as new records with no ordering guarantees. Batch at 1000 keys per 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/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).\
> \
> Prefer this over \`POST .../retry\` when errors are caused by rate-limiting or transient\
> target-system issues. Only errors with a \`retryDataKey\` can be retried — connection-level\
> errors lack one and require a full flow rerun to recover.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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","required":["_id","type","status","createdAt","lastModified"],"description":"A job represents one execution of a flow/export/import (or a retry) in integrator.io.\nJobs are read-only records created by the platform when executions occur.\n\nParent jobs (`type: flow`) carry aggregate counters; child jobs (`type: export` or `import`)\ncarry per-step counters -- do not sum both to avoid double-counting. `_exportId` on a parent\nflow job references the page-generator export, not all exports in the flow.\n","allOf":[{"$ref":"#/components/schemas/ResourceResponse"},{"type":"object","properties":{"_userId":{"type":"string","format":"objectId","readOnly":true,"description":"Owner user id for the job."},"type":{"type":"string","readOnly":true,"description":"Job type.","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":"The export or import resource ID for this child job. Present on child\njobs (`type: export` or `type: import`) — check `type` to determine\nwhether this references an export or import resource."},"_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)."},"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's analytics data expires."},"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":"When true, all export pages have been generated."},"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":"When true, 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":{"description":"Error file artifact (if any).","allOf":[{"$ref":"#/components/schemas/JobErrorFileRef"},{"description":"Error file artifact (if any)."}]},"logMode":{"type":"string","readOnly":true,"description":"Effective logging mode for this job, resolved from the flow's `logging.mode`\nand the account-level logging preference. Common values: `basic` (default),\n`off`, `on`, `debug`."},"__lastPageGeneratorJob":{"type":"boolean","readOnly":true,"description":"When true, indicates the last page-generator job in the sequence. Internal use only."}}}]},"ResourceResponse":{"type":"object","description":"Response","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the resource. Format is a 24-character hexadecimal string."},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was created. Set automatically and cannot be modified."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was last updated. Changes whenever any property is modified."},"deletedAt":{"type":["string","null"],"format":"date-time","readOnly":true,"description":"Timestamp when the resource was soft-deleted. When null or absent, the resource is active."}}},"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).\n\nPrefer this over `POST .../retry` when errors are caused by rate-limiting or transient\ntarget-system issues. Only errors with a `retryDataKey` can be retried — connection-level\nerrors lack one and require a full flow rerun to recover.","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.\
> \
> The \`data\` field shows exactly the payload the runtime tried to submit — compare it against the\
> source system to pinpoint transformation drift. Use \`PUT .../{retryDataKey}/data\` to mutate\
> the snapshot before retrying. Only errors with a \`retryDataKey\` expose this endpoint;\
> connection-class errors are rejected with \`no\_retrydata\_found\`. The \`stage\` field indicates\
> where the retry will resume: \`page\_processor\_import\` re-runs the import (most common),\
> \`page\_generator\` means the error was upstream of the processor.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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."},"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\nThe `data` field shows exactly the payload the runtime tried to submit — compare it against the\nsource system to pinpoint transformation drift. Use `PUT .../{retryDataKey}/data` to mutate\nthe snapshot before retrying. Only errors with a `retryDataKey` expose this endpoint;\nconnection-class errors are rejected with `no_retrydata_found`. The `stage` field indicates\nwhere the retry will resume: `page_processor_import` re-runs the import (most common),\n`page_generator` means the error was upstream of 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.\
> \
> The typical workflow is: \`GET .../{retryDataKey}/data\`, mutate \`data\` locally, \`PUT\` the whole\
> envelope back, then \`POST .../retry\` with the same \`retryDataKey\`. Send the complete envelope\
> — omitted fields are lost, and \`retryDataKey\`, \`stage\`, \`pgExportId\` must match the original GET.\
> Editing the snapshot does not clear the error; it stays open until a subsequent retry or\
> manual resolve.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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."},"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\nThe typical workflow is: `GET .../{retryDataKey}/data`, mutate `data` locally, `PUT` the whole\nenvelope back, then `POST .../retry` with the same `retryDataKey`. Send the complete envelope\n— omitted fields are lost, and `retryDataKey`, `stage`, `pgExportId` must match the original GET.\nEditing the snapshot does not clear the error; it stays open until a subsequent retry or\nmanual resolve.","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.\
> \
> File-based adaptors (FTP, S3, etc.) store retry data as files; record-based adaptors store\
> JSON snapshots accessible via \`GET .../{ retryDataKey}/data\` instead. The signed URL requires\
> no auth headers.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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."}}},"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.\n\nFile-based adaptors (FTP, S3, etc.) store retry data as files; record-based adaptors store\nJSON snapshots accessible via `GET .../{ retryDataKey}/data` instead. The signed URL requires\nno auth headers.","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.\
> \
> The \`time\` and \`response.receivedAt\` fields are epoch milliseconds, useful for correlating\
> with target-system logs. Not every error has a stored trace — record-level errors from\
> non-HTTP adaptors (e.g. NetSuite distributed imports) lack a \`reqAndResKey\`.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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."}}},"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\nThe `time` and `response.receivedAt` fields are epoch milliseconds, useful for correlating\nwith target-system logs. Not every error has a stored trace — record-level errors from\nnon-HTTP adaptors (e.g. NetSuite distributed imports) 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.\
> \
> \*\*Important:\*\* Time parameters (\`time\_lte\`, \`time\_gt\`) must be epoch milliseconds (integers),\
> not ISO 8601 strings.\
> \
> Use \`GET .../requests/{reqAndResKey}\` to drill into individual request/response bodies.\
> \`statusCode\` is returned as a string, not an integer. For oversized bodies stored in S3,\
> follow up with \`GET .../requests/{key}/files/signedURL\`.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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`)."}}}},"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)."}}},"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\n**Important:** Time parameters (`time_lte`, `time_gt`) must be epoch milliseconds (integers),\nnot ISO 8601 strings.\n\nUse `GET .../requests/{reqAndResKey}` to drill into individual request/response bodies.\n`statusCode` is returned as a string, not an integer. For oversized bodies stored in S3,\nfollow up with `GET .../requests/{key}/files/signedURL`.","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 fail with \`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."\`.\
> \
> The underlying error record in \`GET .../errors\` remains after deletion, but its \`reqAndResKey\`\
> pointer will dangle. There is no single "purge all" call — enumerate current errors and collect\
> all \`reqAndResKey\` values to clear the full cache.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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}}}},"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 fail with `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\nThe underlying error record in `GET .../errors` remains after deletion, but its `reqAndResKey`\npointer will dangle. There is no single \"purge all\" call — enumerate current errors and collect\nall `reqAndResKey` values to clear the full cache.","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.\
> \
> Call \`GET .../requests/{reqAndResKey}\` first. If \`request.body\` or \`response.body\` is\
> truncated or missing, use this endpoint to fetch the full payload from S3.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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."}}},"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\nCall `GET .../requests/{reqAndResKey}` first. If `request.body` or `response.body` is\ntruncated or missing, use this endpoint to fetch the full payload from S3.","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\`.\
> \
> The errors batch uses short keys (\`id\` = errorId, \`rdk\` = retryDataKey) to minimize body size.\
> Use \`rdk: ""\` for errors without a \`retryDataKey\` (connection-class errors). This endpoint\
> replaces the full tag set per error — to add a tag without removing existing ones, merge\
> client-side first.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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"}}}}}},"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\nThe errors batch uses short keys (`id` = errorId, `rdk` = retryDataKey) to minimize body size.\nUse `rdk: \"\"` for errors without a `retryDataKey` (connection-class errors). This endpoint\nreplaces the full tag set per error — to add a tag without removing existing ones, merge\nclient-side first.","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.\
> \
> This is a destructive, irreversible operation. The 202 response does not include a job id;\
> there is no way to poll for completion.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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\nThis is a destructive, irreversible operation. The 202 response does not include a job id;\nthere 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.\
> \
> Cancellation is asynchronous — jobs may take a few seconds to fully stop after the 204 is\
> returned.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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\nCancellation is asynchronous — jobs may take a few seconds to fully stop after the 204 is\nreturned.","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.\
> \
> 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.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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)."}}}}}},"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\nNarrow the window with `createdAt_gte` / `createdAt_lte` when there are many runs for the\nflow. Because `status` is silently ignored, filter client-side if you need only completed or\nerrored 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.\
> \
> For detailed per-stage data (HTTP request/response, script \`options.logs\` output), pick an\
> entry and call \`POST .../logs/data/query\` with the corresponding \`stage\`. To stitch an\
> export entry to its downstream imports, use the \`traceKey\` with\
> \`POST .../logs/metadata/query\`.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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."}}},"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."}}},"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\nFor detailed per-stage data (HTTP request/response, script `options.logs` output), pick an\nentry and call `POST .../logs/data/query` with the corresponding `stage`. To stitch an\nexport entry to its downstream imports, use the `traceKey` with\n`POST .../logs/metadata/query`.","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.\
> \
> Pair this with \`logs/data/query\` to build a full per-record trace: this endpoint shows which\
> steps were touched and timing; the data endpoint returns actual payloads. When\
> \`duplicateTraceKey\` is \`true\`, the traceKey was seen on more than one record in the job, so\
> results may mix records from retries or fan-out. Without \`traceKey\` in the request,\
> \`traceView\` is \`false\` and only the single queried step is returned.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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"}}}},"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."}}},"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\nPair this with `logs/data/query` to build a full per-record trace: this endpoint shows which\nsteps were touched and timing; the data endpoint returns actual payloads. When\n`duplicateTraceKey` is `true`, the traceKey was seen on more than one record in the job, so\nresults may mix records from retries or fan-out. Without `traceKey` in the request,\n`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(...)\`.\
> \
> This is typically the terminal call in the drill-down sequence: \`execution-logs\` then\
> \`metadata/query\` then \`data/query\`. For HTTP traces, set \`stage: apiCall\`. A 200 with\
> \`logs: \[]\` means the stage ran but produced no log entry — usually because a script did not\
> call \`options.logs.push()\`, or the stage is not instrumented for that adaptor.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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.","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 vary by the requested stage.","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}}}},"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\nThis is typically the terminal call in the drill-down sequence: `execution-logs` then\n`metadata/query` then `data/query`. For HTTP traces, set `stage: apiCall`. A 200 with\n`logs: []` means the stage ran but produced no log entry — usually because a script did not\ncall `options.logs.push()`, or the stage is not instrumented for that adaptor.","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.\
> \
> Use the \`status\` query parameter to isolate failures within a batch.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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."}}},"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."}}},"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\nUse the `status` query parameter 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 are rejected with \`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.\
> \
> Response entries may carry base64-encoded JSON in \`request.body\` and\
> \`response.body\` fields — decode string bodies before parsing. A 404\
> response is expected for non-HTTP steps (routers, filters); cross-check\
> against the test-run metadata's stage list before treating it as a\
> failure. Test runs are short-lived ephemeral state, so capture logs\
> soon after the run completes.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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 are rejected with `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\nResponse entries may carry base64-encoded JSON in `request.body` and\n`response.body` fields — decode string bodies before parsing. A 404\nresponse is expected for non-HTTP steps (routers, filters); cross-check\nagainst the test-run metadata's stage list before treating it as a\nfailure. Test runs are short-lived ephemeral state, so capture logs\nsoon after the 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).\
> \
> Unknown or already-completed group ids return 404 \`resource\_not\_found\` — only groups with\
> cancellable (queued/running) jobs are accepted.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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/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\nUnknown or already-completed group ids return 404 `resource_not_found` — only groups with\ncancellable (queued/running) jobs are accepted.","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."}}}}}},"204":{"description":"Cancellation requested for remaining jobs in the group. No response body."},"401":{"$ref":"#/components/responses/401-unauthorized"},"404":{"$ref":"#/components/responses/404-not-found"}}}}}}
```

## 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\`.\
> \
> The values are static and identical for all callers — cache them aggressively.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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"}}}}}}}},"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\nThe values are static and identical for all callers — cache them aggressively.","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.\
> \
> The body field is \`flow\` (the API's error message referencing \`flowDoc\`\
> is stale). Every entry referenced by \`flow\.pageGenerators\[].\_exportId\`\
> must exist in \`pageGeneratorMap\` keyed by that id, wrapped as\
> \`{doc, options}\`; same for \`pageProcessorMap\`. Set \`includeStages: true\`\
> to get the stage-by-stage diagnostic array. This endpoint has no side\
> effects — no job is created and no flow state changes.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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":["flowDoc","_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\nThe body field is `flow` (the API's error message referencing `flowDoc`\nis stale). Every entry referenced by `flow.pageGenerators[]._exportId`\nmust exist in `pageGeneratorMap` keyed by that id, wrapped as\n`{doc, options}`; same for `pageProcessorMap`. Set `includeStages: true`\nto get the stage-by-stage diagnostic array. This endpoint has no side\neffects — no job is created and 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.","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.\
> \
> An empty object \`{}\` means no other resources depend on the target — this is also returned for a\
> well-formatted but nonexistent id.

```json
{"openapi":"3.2.0","info":{"title":"Flows","version":"1.0.0"},"tags":[{"name":"Flows","description":"Flows orchestrate how data moves between systems. A flow chains one or more page\ngenerators (exports that produce records) into a pipeline of page processors (lookups\nand imports), with optional routers for conditional branching. Flows run on a cron\nschedule, on demand, or in response to real-time events, and expose endpoints for\nrunning, monitoring, and managing per-step errors.\n\n{% openapi-schemas spec=\"flow\" schemas=\"Flow\" grouped=\"false\" %}"}],"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":"Dot-notation paths within the dependent resource that reference\nthe target resource. `[*]` denotes array elements.","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.","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\nAn empty object `{}` means no other resources depend on the target — this is also returned for a\nwell-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
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
