Clone an Integration with Flows Between Environments Without Using the UI

Hi,

We are managing separate Development and Production environments and need to clone integrations from Development to Production.

Before the environment migration, we were able to clone an integration through the created integration flow. However, after moving to separate Development and Production environments, we are no longer able to perform this.

We would like to know if there is any way to clone an integration from one environment to another using a Celigo flow, instead of doing it manually through the UI.

Requirement

For example:

Development

  • Integration A
  • Flow 1
  • Flow 2
  • Flow 3

We need to clone the complete integration structure to:

Production

  • Integration A
  • Flow 1
  • Flow 2
  • Flow 3

Is there any supported way to achieve this using a Celigo flow ?

We are specifically looking for a solution that allows us to automate this process without manually recreating the integration and flows in the Production environment.

Could you please advise if this is possible and, if so, provide the recommended approach or relevant API documentation?

Thank you.

Hi Geethaka,

What changed is the environment model. Before the migration, Sandbox and Production were two halves of a single account, so a clone request from one side could land on the other. After the migration, each environment is fully isolated: it has its own users, integrations, and connections, and an API token belongs to exactly one environment. The old request now runs entirely inside whichever environment issued the token, which is why the clone stopped landing in Production.

The same endpoint now takes a target environment, so you can keep automating this with a flow. Three things to set up once:

  1. A token from the Development environment. Switch into Development in integrator.io and create the API token there. The user who owns the token also needs Manage access in Production.
  2. The Production environment _id. Call GET /v1/environments and copy the _id of the environment named Production.
  3. A connection map. Call GET /v1/integrations/{devIntegrationId}/clone/preview and note every object with model: Connection. For each one, find the matching connection in Production and record its _id. Mapped connections are reused rather than copied, so map every connection the preview lists.

The clone call is then:

POST https://api.integrator.io/v1/integrations/{devIntegrationId}/clone
Authorization: Bearer <Development token>
Content-Type: application/json

{
  "name": "Integration A",
  "_envId": "<Production environment _id>",
  "connectionMap": {
    "<dev connection _id>": "<prod connection _id>",
    "<dev connection _id>": "<prod connection _id>"
  }
}

If you're not on the US region, swap in your base URL: api.eu.integrator.io, api.au.integrator.io, or api.ca.integrator.io.

In a flow, that's an HTTP connection to your region's API base URL authenticated with the Development token, an HTTP export that calls GET /v1/environments with an output filter keeping record.name equal to Production, and an HTTP import that posts the body above with "_envId": "{{{record._id}}}". The integration ID and connection map don't change between runs, so they can stay hardcoded in the import body. Run the flow whenever you want to publish.

Two things to know before you automate it:

  • Each run creates a new integration in Production, with new _ids for the integration, flows, exports, and imports. Treat it as a replace: disable or delete the previous copy, and expect anything tied to the old IDs, such as webhook listener URLs and error history, to start fresh.
  • Clones created through the API aren't linked for ILM pulls. If you'd rather keep one Production integration and promote changes into it each release (Production keeps its IDs, schedules, and history, and you review a diff before merging), clone once from Development to Production in the UI, then use Revisions > Create Pull in Production for each release. Pulls are UI-only today, so that step can't run from a flow, but you can automate the pre-release snapshot with POST /v1/integrations/{prodIntegrationId}/revisions/create.

If you'd rather run this from CI than from a flow, the Celigo CLI wraps the same call: celigo integrations clone <devIntegrationId> <prodEnvironmentId> --name "Integration A", with the connection map piped in as JSON.

Docs:

Hi,

Thank you for the detailed explanation.

We followed the recommended approach and created two separate connections for the Development and Production environments, using an Admin API token. We are also passing the Production environment _id in the clone request.

However, we are still facing an issue when providing the Production connection IDs in the connectionMap.

We are using an integrator.io connection in the Development environment because our Development integrations are managed in the Development environment. However, using this connection, we are still unable to retrieve the Production connections.

Our clone request is:

{
  "name": "Integration A",
  "_envId": "<Production environment _id>",
  "connectionMap": {
    "<Development connection _id>": "<Production connection _id>"
  }
}

The request returns the following error:

{
  "errors": [
    {
      "code": "invalid_connectionId",
      "message": "The _connectionId provided for the key '642aa3624e32297235f26034': '642aa5bc9ce9ae7c4ece18f3' is invalid."
    }
  ]
}

Could you please confirm how we can retrieve or validate the Production connection IDs for the cross-environment clone?

Also, is there any specific API endpoint or permission that we need to use to retrieve the Production connections while using the integrator.io connection from the Development environment?

If possible, could you please provide a working example of the API requests for:

  1. Getting the Production connection IDs
  2. Creating the cross-environment clone with the connectionMap

Thank you.

Hi Geethaka,

Thanks for the details. That error message pinpointed the problem. My earlier example had the wrong field name: the target environment goes in envId, not _envId. The API ignores _envId, so your request was treated as a clone inside Development, and the Production connection failed validation because it doesn't exist there. Nothing was created, and your connection IDs are most likely fine.

Getting the Production connection IDs

An API token only sees the environment it was created in, so no endpoint or permission will let your Development connection read Production. Use the token from your Production integrator.io connection instead:

GET https://api.integrator.io/v1/connections
Authorization: Bearer <Production token>

Each item's _id is a value for your map. To check a single ID, call GET /v1/connections/{_id} with the same token: if it returns the connection, it's in Production. Connection IDs don't change, so you only need to look them up once and can keep the map hardcoded in your import.

The clone request

Same call as before with the field renamed, sent with the Development token:

POST https://api.integrator.io/v1/integrations/{devIntegrationId}/clone
Authorization: Bearer <Development token>
Content-Type: application/json

{
  "name": "Integration A",
  "envId": "<Production environment _id>",
  "connectionMap": {
    "<Development connection _id>": "<Production connection _id>"
  }
}

Every connection the clone preview lists needs an entry in connectionMap, and each value has to be a Production connection. If one is missing or wrong, you'll get the same invalid_connectionId error naming that key. In your flow, the only change is "envId": "{{{record._id}}}" in the import body.