Environment Configuration Export / Import Guide
This guide explains how to export and import environment configurations in the InCountry Portal. Use it to back up settings, move configuration between environments, or automate updates through scripts and CI/CD pipelines.
What is Export / Import?
Every InCountry environment has a configuration that can be downloaded as a single JSON file and uploaded back later. A typical export includes:
- Activated Countries — which country POPs are active
- Access Policies — data access control rules
- Key-alias mappings — how data fields map to storage keys
- Data Firewall — IP allowlist settings
- AgentCloak (MCP) — AI agent data protection rules
- Border endpoints — redaction and unredaction rules for API traffic
- Resident Functions — serverless function scripts (when present)
The export downloads all of this as one file. The import applies your (edited) JSON back to the environment.
Start from a full export and change only the fields you intend to update. Do not build the JSON from scratch.
Prerequisites
Before you begin, you need:
-
Access to the InCountry Portal with permission to manage the target environment.
-
Your Environment ID — visible in the browser URL when you open an environment:
https://portal.incountry.com/environments/<YOUR-ENVIRONMENT-ID>
Export and Import from the Portal UI
-
Open your environment and scroll to Manage environment configuration.

-
Click Export environment configuration. The browser downloads a JSON file named after your Environment ID.
-
Edit the file as needed (see Editing the configuration below).
-
Click Import environment configuration, select your JSON file, and confirm.
-
If import succeeds, the environment updates immediately. If validation fails, the Portal shows an error and the environment is not changed.
Export again right after import and compare the result with what you uploaded. This confirms your changes were applied.
Choosing credentials for API access
If you want to call export/import from a script or pipeline, you can authenticate with either an API Key or a Migration Client. Both work with the same API endpoints.
Quick comparison
| API Key | Migration Client | |
|---|---|---|
| Where you create it | Organization-level API Keys section | Per-environment Migration client panel |
| What it belongs to | Your organization (can be used for environments in that organization) | A specific environment |
| How you authenticate | Send the key directly: X-API-Key: <key> | Exchange Client ID + Secret for a short-lived token, then use Authorization: Bearer <token> |
| Permissions | export and/or import | env:export and env:import |
| Typical use | Quick scripts, manual automation, small teams | CI/CD pipelines, production automation, enterprise secret management |
Organization-level vs environment-level
This distinction matters when you manage multiple environments:
- API Key is created at the organization level. One key can call export/import for any environment that belongs to your organization, as long as the key has the right scopes (
export,import). You manage keys centrally in the API Keys area of the Portal. - Migration Client is created per environment. Each environment gets its own Client ID and Client Secret, shown in that environment's configuration panel. This makes it clear which environment a pipeline is allowed to touch.
In both cases, the Portal verifies that the target environment belongs to your organization before allowing the operation.
Which one should I use?
API Key is a good fit when:
- You want the simplest possible setup — one header, no token exchange
- You are running a one-off script or internal tool
- You prefer managing credentials in one place for your whole organization
Migration Client is a good fit when:
- You are wiring export/import into CI/CD (GitHub Actions, Jenkins, GitLab CI, etc.)
- Your security team expects OAuth2-style machine-to-machine authentication
- You want credentials scoped to a single environment so dev/staging/prod pipelines stay separate
- You want each API call to use a short-lived access token rather than sending a long-lived key on every request
API Keys can absolutely be used in CI/CD — many teams do. Migration Client is the recommended default for production pipelines because it aligns better with common enterprise security practices (short-lived tokens, per-environment isolation, standard OAuth2 flows). If your team already has a working API Key pipeline and your security policy allows it, you do not need to switch.
API Key setup and usage
-
In the Portal, open the API Keys section for your organization and click Create API Key.

-
Configure:
- Name — a descriptive label (e.g.,
config-sync-staging) - Scopes — enable Export and/or Import as needed
- Expiration — choose Never, 30 days, 90 days, or a custom date
- Name — a descriptive label (e.g.,
-
Click Create and copy the key immediately. It is shown only once.
-
Use the key in your script or pipeline:
# Exportcurl -sS \-H "X-API-Key: <YOUR_API_KEY>" \"https://portal.incountry.com/api/environments/<ENV_ID>/export" \-o config.json# Importcurl -sS -X POST \-H "X-API-Key: <YOUR_API_KEY>" \-H "Content-Type: application/json" \--data-binary "@config.json" \"https://portal.incountry.com/api/environments/<ENV_ID>/import"
Migration Client setup and usage
-
Open the target environment, scroll to Manage environment configuration, and under Migration client click Create migration client.

-
The Portal displays everything your pipeline needs:
Field Description Environment ID The target environment UUID Authentication endpoint OAuth2 token URL (e.g., https://auth.incountry.com/oauth2/token)Portal address API base URL (e.g., https://portal.incountry.com/api)Scope env:export env:importClient ID OAuth2 client identifier Client Secret Copy now — shown only once -
Store the credentials in your secrets manager (e.g., GitHub Actions secrets, Azure Key Vault).
-
In your pipeline, exchange credentials for a token, then call the API:
TOKEN="$(curl -sS -X POST "<AUTH_ENDPOINT>" \-d "grant_type=client_credentials" \-d "client_id=<CLIENT_ID>" \-d "client_secret=<CLIENT_SECRET>" \-d "scope=env:export env:import" \| jq -r '.access_token')"# Exportcurl -sS \-H "Authorization: Bearer ${TOKEN}" \"<PORTAL_ADDRESS>/environments/<ENV_ID>/export" \-o config.json# Importcurl -sS -X POST \-H "Authorization: Bearer ${TOKEN}" \-H "Content-Type: application/json" \--data-binary "@config.json" \"<PORTAL_ADDRESS>/environments/<ENV_ID>/import"
If you lose the Client Secret, click Renew in the Migration client panel to generate a new one. Update your pipeline secrets afterward.
Automating with CI/CD
Both API Key and Migration Client support automated pipelines. A typical GitOps-style loop looks like this:
- Export the current configuration from the source environment.
- Apply changes programmatically (patch JSON fields, inject environment-specific values).
- Import the modified configuration to the target environment.
- Verify by re-exporting and comparing with the expected state.
GitHub Actions example (Migration Client)
name: Sync environment configuration
on:
push:
branches: [main]
paths:
- 'templates/**'
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Get OAuth2 token
id: token
run: |
TOKEN=$(curl -sS -X POST "${{ secrets.AUTH_ENDPOINT }}" \
-d "grant_type=client_credentials" \
-d "client_id=${{ secrets.CLIENT_ID }}" \
-d "client_secret=${{ secrets.CLIENT_SECRET }}" \
-d "scope=env:export env:import" \
| jq -r '.access_token')
echo "token=$TOKEN" >> "$GITHUB_OUTPUT"
- name: Export current configuration
run: |
curl -sS -H "Authorization: Bearer ${{ steps.token.outputs.token }}" \
"${{ secrets.PORTAL_ADDRESS }}/environments/${{ secrets.ENV_ID }}/export" \
-o baseline.json
- name: Apply template overrides
run: |
jq '. * $overlay' baseline.json \
--slurpfile overlay templates/agentcloak.template.json \
> final.json
- name: Import updated configuration
run: |
curl -sS -X POST \
-H "Authorization: Bearer ${{ steps.token.outputs.token }}" \
-H "Content-Type: application/json" \
--data-binary "@final.json" \
"${{ secrets.PORTAL_ADDRESS }}/environments/${{ secrets.ENV_ID }}/import"
Required secrets:
| Secret | Value |
|---|---|
AUTH_ENDPOINT | Authentication endpoint from Migration client |
CLIENT_ID | Client ID from Migration client |
CLIENT_SECRET | Client Secret from Migration client |
PORTAL_ADDRESS | Portal address from Migration client |
ENV_ID | Your Environment ID |
To use an API Key instead, replace the token step with -H "X-API-Key: ${{ secrets.API_KEY }}" on the export and import curl commands.
Editing the configuration
Edit the downloaded JSON to make your changes. Common modifications:
| What to change | Where in the JSON |
|---|---|
| Border target URL | countries.<key>.border.configurations[n].target |
| Add/update redaction rule | countries.<key>.border.configurations[n].redactions[n].strategies |
| CORS allowed origin | countries.<key>.border.configurations[n].cors.Access-Control-Allow-Origin |
| Key-alias mapping | keyMapping.<table>.fields.<field>.map_to |
| Firewall IP allowlist | dataFirewall.countries.<country>.whitelist.ip |
| AgentCloak MCP server URL | countries.<key>.agentCloak.mcpServers[n].mcp_server_url |
Redaction strategy reference
| Strategy | Best for | Example fields |
|---|---|---|
alphaNumericPersistent | Names (deterministic) | $.fullName, $.firstName |
emailPersistent | Emails (deterministic) | $.email, $.contactEmail |
numeric | Phone numbers, amounts | $.phone, $.mobile |
defaultDateISO | Dates (fixed to 1970-01-01) | $.dateOfBirth, $.dob |
alphaNumeric | Addresses, URLs, generic text | $.address, $.url |
password | Passwords, secrets | $.password, $.secret |
fixed | Fixed replacement value | $.country, $.locale |
masking | Partial masking (shows prefix) | $.cardNumber, $.name |
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Import returns 400 | Malformed JSON or missing required fields | Validate JSON; ensure version, environmentId, and countries are present |
| Import returns 401 | Invalid or expired API key / token | Regenerate credentials in the Portal, or fetch a new OAuth token |
| Import returns 403 | Missing export or import scope | Re-create the API key with the correct scopes, or verify the Migration client scope is env:export env:import |
| Import returns 403 (API Key) | Environment does not belong to your organization | Use an environment within the same organization as the API key |
| Fields unchanged after import | Based on stale or hand-built JSON | Always start from a fresh export |
| Client Secret lost | Panel was closed before copying | Click Renew in the Migration client panel and update your pipeline secrets |



