Skip to main content

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.

Important

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:

  1. Access to the InCountry Portal with permission to manage the target environment.

  2. Your Environment ID — visible in the browser URL when you open an environment:

    https://portal.incountry.com/environments/<YOUR-ENVIRONMENT-ID>

    Environment URL showing the UUID after /environments/


Export and Import from the Portal UI

  1. Open your environment and scroll to Manage environment configuration.

    Manage environment configuration widget showing Export and Import rows

  2. Click Export environment configuration. The browser downloads a JSON file named after your Environment ID.

  3. Edit the file as needed (see Editing the configuration below).

  4. Click Import environment configuration, select your JSON file, and confirm.

  5. If import succeeds, the environment updates immediately. If validation fails, the Portal shows an error and the environment is not changed.

tip

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 KeyMigration Client
Where you create itOrganization-level API Keys sectionPer-environment Migration client panel
What it belongs toYour organization (can be used for environments in that organization)A specific environment
How you authenticateSend the key directly: X-API-Key: <key>Exchange Client ID + Secret for a short-lived token, then use Authorization: Bearer <token>
Permissionsexport and/or importenv:export and env:import
Typical useQuick scripts, manual automation, small teamsCI/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
note

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

  1. In the Portal, open the API Keys section for your organization and click Create API Key.

    Create API Key dialog showing Name, Scopes, and Expiration fields

  2. 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
  3. Click Create and copy the key immediately. It is shown only once.

  4. Use the key in your script or pipeline:

    # Export
    curl -sS \
    -H "X-API-Key: <YOUR_API_KEY>" \
    "https://portal.incountry.com/api/environments/<ENV_ID>/export" \
    -o config.json

    # Import
    curl -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

  1. Open the target environment, scroll to Manage environment configuration, and under Migration client click Create migration client.

    Migration client credentials panel showing Environment ID, Auth endpoint, Portal address, Scope, Client ID, and Client Secret fields

  2. The Portal displays everything your pipeline needs:

    FieldDescription
    Environment IDThe target environment UUID
    Authentication endpointOAuth2 token URL (e.g., https://auth.incountry.com/oauth2/token)
    Portal addressAPI base URL (e.g., https://portal.incountry.com/api)
    Scopeenv:export env:import
    Client IDOAuth2 client identifier
    Client SecretCopy now — shown only once
  3. Store the credentials in your secrets manager (e.g., GitHub Actions secrets, Azure Key Vault).

  4. 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')"

    # Export
    curl -sS \
    -H "Authorization: Bearer ${TOKEN}" \
    "<PORTAL_ADDRESS>/environments/<ENV_ID>/export" \
    -o config.json

    # Import
    curl -sS -X POST \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Content-Type: application/json" \
    --data-binary "@config.json" \
    "<PORTAL_ADDRESS>/environments/<ENV_ID>/import"
Warning

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:

  1. Export the current configuration from the source environment.
  2. Apply changes programmatically (patch JSON fields, inject environment-specific values).
  3. Import the modified configuration to the target environment.
  4. 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:

SecretValue
AUTH_ENDPOINTAuthentication endpoint from Migration client
CLIENT_IDClient ID from Migration client
CLIENT_SECRETClient Secret from Migration client
PORTAL_ADDRESSPortal address from Migration client
ENV_IDYour 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 changeWhere in the JSON
Border target URLcountries.<key>.border.configurations[n].target
Add/update redaction rulecountries.<key>.border.configurations[n].redactions[n].strategies
CORS allowed origincountries.<key>.border.configurations[n].cors.Access-Control-Allow-Origin
Key-alias mappingkeyMapping.<table>.fields.<field>.map_to
Firewall IP allowlistdataFirewall.countries.<country>.whitelist.ip
AgentCloak MCP server URLcountries.<key>.agentCloak.mcpServers[n].mcp_server_url

Redaction strategy reference

StrategyBest forExample fields
alphaNumericPersistentNames (deterministic)$.fullName, $.firstName
emailPersistentEmails (deterministic)$.email, $.contactEmail
numericPhone numbers, amounts$.phone, $.mobile
defaultDateISODates (fixed to 1970-01-01)$.dateOfBirth, $.dob
alphaNumericAddresses, URLs, generic text$.address, $.url
passwordPasswords, secrets$.password, $.secret
fixedFixed replacement value$.country, $.locale
maskingPartial masking (shows prefix)$.cardNumber, $.name

Troubleshooting

SymptomLikely causeFix
Import returns 400Malformed JSON or missing required fieldsValidate JSON; ensure version, environmentId, and countries are present
Import returns 401Invalid or expired API key / tokenRegenerate credentials in the Portal, or fetch a new OAuth token
Import returns 403Missing export or import scopeRe-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 organizationUse an environment within the same organization as the API key
Fields unchanged after importBased on stale or hand-built JSONAlways start from a fresh export
Client Secret lostPanel was closed before copyingClick Renew in the Migration client panel and update your pipeline secrets