{
  "info": {
    "_postman_id": "cf9df7c6-9a55-4601-be03-b3abe356c571",
    "name": "eXate API Guide - Management, Tenancy & Data Protection",
    "description": "Companion collection for the eXate API Guide docs page.\n\nCovers four workflows in order: (1) creating a tenancy, (2) an optional system configuration change for how protected values are formatted, (3) setting up Policies, Claims, and a Manifest through the Management API, and (4) running a Protect call through the Execution API.\n\n**Before you start:**\n- Tenancy creation requires a Global RO client ID and secret, provided by eXate.\n- Everything else requires an Application, subscription, and API Key from the Developer Portal, see the API Guide docs page for how to get these.\n- Replace every `CHANGE_ME` value in the collection variables before running any request.\n\nNone of the variable defaults in this collection are real credentials, replace them with your own.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "item": [
    {
      "name": "1. Authentication",
      "item": [
        {
          "name": "Generate Global Admin Token",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/x-www-form-urlencoded"
              }
            ],
            "url": {
              "raw": "https://{{eXate_Identity_URL}}/connect/token",
              "host": [
                "https://{{eXate_Identity_URL}}/connect/token"
              ]
            },
            "body": {
              "mode": "urlencoded",
              "urlencoded": [
                {
                  "key": "client_id",
                  "value": "{{eXateGlobalRO}}",
                  "type": "text"
                },
                {
                  "key": "client_secret",
                  "value": "{{eXateGlobalSecret}}",
                  "type": "text"
                },
                {
                  "key": "grant_type",
                  "value": "password",
                  "type": "text"
                },
                {
                  "key": "username",
                  "value": "{{eXateGlobalUser}}",
                  "type": "text"
                },
                {
                  "key": "password",
                  "value": "{{eXateGlobalPass}}",
                  "type": "text"
                }
              ]
            },
            "description": "Requires a Global RO client and secret, provided by eXate. Used only for tenancy management, not day-to-day API calls."
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "var jsonData = JSON.parse(responseBody);",
                  "pm.collectionVariables.set(\"ACCESS_TOKEN\", \"Bearer \" + jsonData.access_token);"
                ],
                "type": "text/javascript"
              }
            }
          ]
        },
        {
          "name": "Generate Tenancy Token",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "https://{{eXate_URL}}/apigator/identity/v1/token",
              "host": [
                "https://{{eXate_URL}}/apigator/identity/v1/token"
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "body": {
              "mode": "urlencoded",
              "urlencoded": [
                {
                  "key": "client_id",
                  "value": "{{NewTenancyClientId}}",
                  "type": "text"
                },
                {
                  "key": "client_secret",
                  "value": "{{NewTenancySecret}}",
                  "type": "text"
                },
                {
                  "key": "grant_type",
                  "value": "client_credentials",
                  "type": "text"
                }
              ]
            },
            "description": "Scoped to a single tenancy. Used for all Management and Execution API calls below."
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "var jsonData = JSON.parse(responseBody);",
                  "pm.collectionVariables.set(\"TENANCY_ACCESS_TOKEN\", \"Bearer \" + jsonData.access_token);"
                ],
                "type": "text/javascript"
              }
            }
          ]
        }
      ],
      "description": "Two separate tokens: a Global Admin token for creating tenancies, and a Tenancy token scoped to one tenancy for everything else."
    },
    {
      "name": "2. Tenancy Management",
      "item": [
        {
          "name": "Create Tenancy",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "accept",
                "value": "application/json, text/plain, */*"
              },
              {
                "key": "authorization",
                "value": "{{ACCESS_TOKEN}}"
              }
            ],
            "url": {
              "raw": "https://{{eXate_Tenancy_API}}/api/administration/Firm",
              "host": [
                "https://{{eXate_Tenancy_API}}/api/administration/Firm"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"firmId\": 0,\n  \"firmName\": \"CHANGE_ME\",\n  \"firmDomainName\": \"\",\n  \"zone\": 0,\n  \"ruleConfiguration\": 2,\n  \"isAllowFourEyeCheck\": false,\n  \"isActive\": true,\n  \"firmSizeId\": 1,\n  \"fullName\": \"CHANGE_ME\",\n  \"email\": \"{{NewTenancyAdminEmail}}\",\n  \"password\": \"{{NewTenancyAdminPass}}\",\n  \"department\": \"Management\",\n  \"dataUsage\": \"Legitimate use\",\n  \"countryCode\": \"GB\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Creates a new tenancy (firm). Requires the Global Admin token. After this, an eXate admin creates the tenancy's client credentials, see the manual step below."
          },
          "response": []
        },
        {
          "name": "Manual step: create tenancy client credentials",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "",
              "host": [
                ""
              ]
            },
            "description": "This step is performed by an eXate administrator, not via API: once the tenancy exists, a client ID and secret are issued for it. Populate NewTenancyClientId and NewTenancySecret with those values before running Generate Tenancy Token."
          },
          "response": []
        }
      ],
      "description": "Create a new tenancy, then obtain its client credentials before authenticating as that tenancy."
    },
    {
      "name": "3. System Configuration: Pseudonymisation Delimiter",
      "item": [
        {
          "name": "Create system config entry",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "authorization",
                "value": "{{TENANCY_ACCESS_TOKEN}}"
              }
            ],
            "url": {
              "raw": "https://{{eXate_Vault}}/api/system-config",
              "host": [
                "https://{{eXate_Vault}}/api/system-config"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"Id\": 0,\n  \"Name\": \"PseudonymiseDelimiter\",\n  \"CreatedDate\": \"2026-01-01T00:00:00.000Z\",\n  \"CreatedBy\": \"CHANGE_ME\",\n  \"UpdatedDate\": \"2026-01-01T00:00:00.000Z\",\n  \"UpdatedBy\": \"CHANGE_ME\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Creates the system config entry that governs how pseudonymised values are formatted. By default, a pseudonymised value is returned as metadata plus a delimiter plus the protected fragment. If a downstream system's validation rejects the default delimiter characters, use this and the three requests below to override them.\n\nCopy the Id from the response into the PseudonymiseDelimiterConfigId variable before running the next three requests."
          },
          "response": []
        },
        {
          "name": "Set Start Identifier",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "authorization",
                "value": "{{TENANCY_ACCESS_TOKEN}}"
              }
            ],
            "url": {
              "raw": "https://{{eXate_Vault}}/api/system-config-value",
              "host": [
                "https://{{eXate_Vault}}/api/system-config-value"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"Id\": 0,\n  \"SystemConfigId\": \"{{PseudonymiseDelimiterConfigId}}\",\n  \"ConfigKey\": \"StartIdentifier\",\n  \"ConfigValue\": \"\",\n  \"CreatedDate\": \"2026-01-01T00:00:00.000Z\",\n  \"CreatedBy\": \"\",\n  \"UpdatedDate\": \"2026-01-01T00:00:00.000Z\",\n  \"UpdatedBy\": \"\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Sets the character(s) that mark the start of the metadata portion. Leave ConfigValue empty to use no start marker."
          },
          "response": []
        },
        {
          "name": "Set End Identifier",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "authorization",
                "value": "{{TENANCY_ACCESS_TOKEN}}"
              }
            ],
            "url": {
              "raw": "https://{{eXate_Vault}}/api/system-config-value",
              "host": [
                "https://{{eXate_Vault}}/api/system-config-value"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"Id\": 0,\n  \"SystemConfigId\": \"{{PseudonymiseDelimiterConfigId}}\",\n  \"ConfigKey\": \"EndIdentifier\",\n  \"ConfigValue\": \"\",\n  \"CreatedDate\": \"2026-01-01T00:00:00.000Z\",\n  \"CreatedBy\": \"\",\n  \"UpdatedDate\": \"2026-01-01T00:00:00.000Z\",\n  \"UpdatedBy\": \"\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Sets the character(s) that mark the end of the metadata portion. Leave ConfigValue empty to use no end marker."
          },
          "response": []
        },
        {
          "name": "Set Split Identifier",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "authorization",
                "value": "{{TENANCY_ACCESS_TOKEN}}"
              }
            ],
            "url": {
              "raw": "https://{{eXate_Vault}}/api/system-config-value",
              "host": [
                "https://{{eXate_Vault}}/api/system-config-value"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"Id\": 0,\n  \"SystemConfigId\": \"{{PseudonymiseDelimiterConfigId}}\",\n  \"ConfigKey\": \"SplitIdentifier\",\n  \"ConfigValue\": \",\",\n  \"CreatedDate\": \"2026-01-01T00:00:00.000Z\",\n  \"CreatedBy\": \"\",\n  \"UpdatedDate\": \"2026-01-01T00:00:00.000Z\",\n  \"UpdatedBy\": \"\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Sets the character that separates the metadata from the protected fragment itself. Default is a comma, change this if a comma breaks downstream validation."
          },
          "response": []
        },
        {
          "name": "Set Protection Version",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "authorization",
                "value": "{{API_Key}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "https://{{eXate_Vault}}/api/protection-version",
              "host": [
                "https://{{eXate_Vault}}/api/protection-version"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"Id\": 0,\n  \"Jobtype\": \"Pseudonymise\",\n  \"ProtectionHandler\": \"2\",\n  \"CreatedBy\": \"\",\n  \"UpdatedBy\": \"\",\n  \"CreatedOn\": \"2026-01-01T00:00:00.000Z\",\n  \"UpdatedOn\": \"2026-01-01T00:00:00.000Z\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Sets which protection handler version pseudonymisation jobs use. Only needed if you've been told to pin or upgrade the handler version."
          },
          "response": []
        }
      ],
      "description": "System-level settings, separate from any single Policy or Manifest. By default, a pseudonymised (masked/tokenised) value is returned as metadata, a delimiter, then the protected fragment. If a downstream system's validation breaks on the default delimiter characters, these requests let you override the start, end, and split identifiers used to build that value, without changing the underlying protection itself."
    },
    {
      "name": "4. Policy Setup (Management API)",
      "item": [
        {
          "name": "Create Claim Pack",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Api-Key",
                "value": "{{API_Key}}",
                "type": "text"
              },
              {
                "key": "X-Resource-Token",
                "value": "{{TENANCY_ACCESS_TOKEN}}",
                "type": "text"
              },
              {
                "key": "X-Request-ID",
                "value": "{{$guid}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "https://{{eXate_URL}}/tenant/management/v1/claimpack",
              "host": [
                "https://{{eXate_URL}}/tenant/management/v1/claimpack"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"claimPackName\": \"Management Data Access\",\n  \"claimPackDefinition\": [\n    {\n      \"claimKey\": \"Department\",\n      \"claimOperator\": \"NONE\",\n      \"claimValue\": \"Management\",\n      \"claimCondition\": \"Equals\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Creates a reusable Claim Pack, a condition checked against the requester before a Policy grants unprotected access."
          },
          "response": []
        },
        {
          "name": "Create Policy Pack",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "{{TENANCY_ACCESS_TOKEN}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "https://rules-{{eXate_URL}}/api/rulepacks",
              "host": [
                "https://rules-{{eXate_URL}}/api/rulepacks"
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"RulePackName\": \"Customer Data Policies\",\n  \"RulePackDescription\": \"Policies protecting customer data fields\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Creates the container that holds one or more Policies. Called \"RulePack\" in the API schema, this is what the docs and portal call a Policy Pack."
          },
          "response": []
        },
        {
          "name": "Create Policy",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Api-Key",
                "value": "{{API_Key}}",
                "type": "text"
              },
              {
                "key": "X-Resource-Token",
                "value": "{{TENANCY_ACCESS_TOKEN}}",
                "type": "text"
              },
              {
                "key": "X-Request-ID",
                "value": "{{$guid}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "https://{{eXate_URL}}/tenant/management/v1/rule",
              "host": [
                "https://{{eXate_URL}}/tenant/management/v1/rule"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"ruleState\": \"Live\",\n  \"rulePackName\": \"Customer Data Policies\",\n  \"ruleName\": \"Marketing Access\",\n  \"attributeList\": [\n    \"FirstName\",\n    \"LastName\"\n  ],\n  \"countryAccessList\": [\n    {\n      \"countryCode\": \"GB\",\n      \"sharedWith\": [\n        \"GB\",\n        \"ES\"\n      ]\n    }\n  ],\n  \"claimsList\": [\n    {\n      \"claimPackName\": \"Management Data Access\"\n    }\n  ],\n  \"usagePolicyList\": [\n    {\n      \"usagePurposeName\": \"Legitimate Use\",\n      \"allowUsage\": true,\n      \"consentRequired\": false\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Creates a Policy within the Policy Pack above: which Attributes it protects (FirstName, LastName), which countries it applies to, which Claim Pack it checks, and the allowed Purpose of Use. Called \"Rule\" in the API schema."
          },
          "response": []
        },
        {
          "name": "Create Manifest",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Api-Key",
                "value": "{{API_Key}}",
                "type": "text"
              },
              {
                "key": "X-Resource-Token",
                "value": "{{TENANCY_ACCESS_TOKEN}}",
                "type": "text"
              },
              {
                "key": "X-Request-ID",
                "value": "{{$guid}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "https://{{eXate_URL}}/tenant/management/v1/entitlement",
              "host": [
                "https://{{eXate_URL}}/tenant/management/v1/entitlement"
              ]
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"entitlements\": [\n    {\n      \"entitlementKey\": \"HelloWorld\",\n      \"entitlementValidity\": {\n        \"validFrom\": \"2026-01-01T00:00:00Z\",\n        \"validEnd\": null\n      },\n      \"entitlementState\": \"Draft\",\n      \"entitlementTags\": [\n        {\n          \"metaName\": \"Notify\",\n          \"metaValue\": \"true\"\n        }\n      ],\n      \"samplePayload\": \"{\\\"employees\\\": {\\\"employee\\\": [{\\\"id\\\": \\\"1\\\", \\\"firstName\\\": \\\"Robert\\\", \\\"lastName\\\": \\\"Brownforest\\\", \\\"fullName\\\": \\\"Robert Brownforest\\\", \\\"DOB\\\": \\\"18/12/1965\\\", \\\"email\\\": \\\"RB1@example.com\\\"}]}}\",\n      \"dataSetType\": \"JSON\"\n    }\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Creates a Manifest (called \"entitlement\" in the API schema) named HelloWorld, mapping a simple sample JSON payload so eXate knows which fields correspond to which Attributes. Replace samplePayload with your own data's structure."
          },
          "response": []
        }
      ],
      "description": "Builds the objects a Protect call needs: a Claim Pack, a Policy Pack containing a Policy, and a Manifest describing your data's shape."
    },
    {
      "name": "5. Data Protection (Execution API)",
      "item": [
        {
          "name": "Run Protect Call",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Api-Key",
                "value": "{{API_Key}}",
                "type": "text"
              },
              {
                "key": "X-Data-Set-Type",
                "value": "JSON",
                "type": "text"
              },
              {
                "key": "X-Resource-Token",
                "value": "{{TENANCY_ACCESS_TOKEN}}",
                "type": "text"
              },
              {
                "key": "X-Request-ID",
                "value": "{{$guid}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "https://{{eXate_URL}}/apigator/protect/v1/dataset",
              "host": [
                "https://{{eXate_URL}}/apigator/protect/v1/dataset"
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"countryCode\": \"GB\",\n  \"dataOwningCountryCode\": \"GB\",\n  \"manifestName\": \"HelloWorld\",\n  \"jobType\": \"Restrict\",\n  \"dataSet\": \"{'employees': {'employee': [{'id': '1','firstName': 'Robert','lastName': 'Brownforest','fullName': 'Robert Brownforest','DOB': '18/12/1965','email': 'RB1@example.com'}]}}\",\n  \"protectNullValues\": true,\n  \"preserveStringLength\": false,\n  \"snapshotDate\": \"2026-01-01T00:00:00Z\",\n  \"restrictedText\": \"*********\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "description": "Sends the sample payload through the HelloWorld Manifest for protection. jobType \"Restrict\" applies the default PET to any field the requester isn't entitled to see unprotected, based on the Policy created above.\n\nsnapshotDate seeds deterministic masking, the same input produces the same masked output on every run. Remove it, or vary it, if you want non-deterministic output instead."
          },
          "response": []
        }
      ],
      "description": "Calls the Execution API to actually protect a payload, using the Manifest and Policy set up in the previous section."
    }
  ],
  "variable": [
    {
      "key": "eXate_Identity_URL",
      "value": "identity.test.exate.co",
      "type": "string"
    },
    {
      "key": "eXate_URL",
      "value": "api.test.exate.co",
      "type": "string"
    },
    {
      "key": "eXate_Tenancy_API",
      "value": "staticdata-api.test.exate.co",
      "type": "string"
    },
    {
      "key": "eXate_Vault",
      "value": "vault-api.test.exate.co",
      "type": "string"
    },
    {
      "key": "eXateGlobalRO",
      "value": "CHANGE_ME",
      "type": "string"
    },
    {
      "key": "eXateGlobalSecret",
      "value": "CHANGE_ME",
      "type": "string"
    },
    {
      "key": "eXateGlobalUser",
      "value": "CHANGE_ME",
      "type": "string"
    },
    {
      "key": "eXateGlobalPass",
      "value": "CHANGE_ME",
      "type": "string"
    },
    {
      "key": "ACCESS_TOKEN",
      "value": "Do not set manually, populated by Generate Global Admin Token",
      "type": "string"
    },
    {
      "key": "NewTenancyAdminEmail",
      "value": "CHANGE_ME",
      "type": "string"
    },
    {
      "key": "NewTenancyAdminPass",
      "value": "CHANGE_ME",
      "type": "string"
    },
    {
      "key": "NewTenancyClientId",
      "value": "CHANGE_ME",
      "type": "string"
    },
    {
      "key": "NewTenancySecret",
      "value": "CHANGE_ME",
      "type": "string"
    },
    {
      "key": "TENANCY_ACCESS_TOKEN",
      "value": "Do not set manually, populated by Generate Tenancy Token",
      "type": "string"
    },
    {
      "key": "API_Key",
      "value": "CHANGE_ME",
      "type": "string"
    },
    {
      "key": "PseudonymiseDelimiterConfigId",
      "value": "CHANGE_ME",
      "type": "string"
    }
  ]
}