Create GCP Apigee Organizations

The gcp:apigee/organization:Organization resource, part of the Pulumi GCP provider, provisions the top-level Apigee container that defines regional placement, network connectivity, and encryption settings. This guide focuses on three capabilities: VPC network integration through Service Networking, data residency configuration for compliance, and customer-managed encryption with Cloud KMS.

Apigee organizations require a GCP project with the Apigee API enabled and may reference VPC networks, KMS keys, and Service Networking connections. The examples are intentionally small. Combine them with your own network infrastructure and security policies.

Connect an organization to a VPC network

Most deployments connect the organization to a VPC network through Service Networking, enabling runtime instances to access databases and internal services.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const current = gcp.organizations.getClientConfig({});
const apigeeNetwork = new gcp.compute.Network("apigee_network", {name: "apigee-network"});
const apigeeRange = new gcp.compute.GlobalAddress("apigee_range", {
    name: "apigee-range",
    purpose: "VPC_PEERING",
    addressType: "INTERNAL",
    prefixLength: 16,
    network: apigeeNetwork.id,
});
const apigeeVpcConnection = new gcp.servicenetworking.Connection("apigee_vpc_connection", {
    network: apigeeNetwork.id,
    service: "servicenetworking.googleapis.com",
    reservedPeeringRanges: [apigeeRange.name],
});
const org = new gcp.apigee.Organization("org", {
    analyticsRegion: "us-central1",
    projectId: current.then(current => current.project),
    authorizedNetwork: apigeeNetwork.id,
}, {
    dependsOn: [apigeeVpcConnection],
});
import pulumi
import pulumi_gcp as gcp

current = gcp.organizations.get_client_config()
apigee_network = gcp.compute.Network("apigee_network", name="apigee-network")
apigee_range = gcp.compute.GlobalAddress("apigee_range",
    name="apigee-range",
    purpose="VPC_PEERING",
    address_type="INTERNAL",
    prefix_length=16,
    network=apigee_network.id)
apigee_vpc_connection = gcp.servicenetworking.Connection("apigee_vpc_connection",
    network=apigee_network.id,
    service="servicenetworking.googleapis.com",
    reserved_peering_ranges=[apigee_range.name])
org = gcp.apigee.Organization("org",
    analytics_region="us-central1",
    project_id=current.project,
    authorized_network=apigee_network.id,
    opts = pulumi.ResourceOptions(depends_on=[apigee_vpc_connection]))
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/apigee"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/servicenetworking"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		current, err := organizations.GetClientConfig(ctx, map[string]interface{}{}, nil)
		if err != nil {
			return err
		}
		apigeeNetwork, err := compute.NewNetwork(ctx, "apigee_network", &compute.NetworkArgs{
			Name: pulumi.String("apigee-network"),
		})
		if err != nil {
			return err
		}
		apigeeRange, err := compute.NewGlobalAddress(ctx, "apigee_range", &compute.GlobalAddressArgs{
			Name:         pulumi.String("apigee-range"),
			Purpose:      pulumi.String("VPC_PEERING"),
			AddressType:  pulumi.String("INTERNAL"),
			PrefixLength: pulumi.Int(16),
			Network:      apigeeNetwork.ID(),
		})
		if err != nil {
			return err
		}
		apigeeVpcConnection, err := servicenetworking.NewConnection(ctx, "apigee_vpc_connection", &servicenetworking.ConnectionArgs{
			Network: apigeeNetwork.ID(),
			Service: pulumi.String("servicenetworking.googleapis.com"),
			ReservedPeeringRanges: pulumi.StringArray{
				apigeeRange.Name,
			},
		})
		if err != nil {
			return err
		}
		_, err = apigee.NewOrganization(ctx, "org", &apigee.OrganizationArgs{
			AnalyticsRegion:   pulumi.String("us-central1"),
			ProjectId:         pulumi.String(current.Project),
			AuthorizedNetwork: apigeeNetwork.ID(),
		}, pulumi.DependsOn([]pulumi.Resource{
			apigeeVpcConnection,
		}))
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var current = Gcp.Organizations.GetClientConfig.Invoke();

    var apigeeNetwork = new Gcp.Compute.Network("apigee_network", new()
    {
        Name = "apigee-network",
    });

    var apigeeRange = new Gcp.Compute.GlobalAddress("apigee_range", new()
    {
        Name = "apigee-range",
        Purpose = "VPC_PEERING",
        AddressType = "INTERNAL",
        PrefixLength = 16,
        Network = apigeeNetwork.Id,
    });

    var apigeeVpcConnection = new Gcp.ServiceNetworking.Connection("apigee_vpc_connection", new()
    {
        Network = apigeeNetwork.Id,
        Service = "servicenetworking.googleapis.com",
        ReservedPeeringRanges = new[]
        {
            apigeeRange.Name,
        },
    });

    var org = new Gcp.Apigee.Organization("org", new()
    {
        AnalyticsRegion = "us-central1",
        ProjectId = current.Apply(getClientConfigResult => getClientConfigResult.Project),
        AuthorizedNetwork = apigeeNetwork.Id,
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            apigeeVpcConnection,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.compute.GlobalAddress;
import com.pulumi.gcp.compute.GlobalAddressArgs;
import com.pulumi.gcp.servicenetworking.Connection;
import com.pulumi.gcp.servicenetworking.ConnectionArgs;
import com.pulumi.gcp.apigee.Organization;
import com.pulumi.gcp.apigee.OrganizationArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        final var current = OrganizationsFunctions.getClientConfig(%!v(PANIC=Format method: runtime error: invalid memory address or nil pointer dereference);

        var apigeeNetwork = new Network("apigeeNetwork", NetworkArgs.builder()
            .name("apigee-network")
            .build());

        var apigeeRange = new GlobalAddress("apigeeRange", GlobalAddressArgs.builder()
            .name("apigee-range")
            .purpose("VPC_PEERING")
            .addressType("INTERNAL")
            .prefixLength(16)
            .network(apigeeNetwork.id())
            .build());

        var apigeeVpcConnection = new Connection("apigeeVpcConnection", ConnectionArgs.builder()
            .network(apigeeNetwork.id())
            .service("servicenetworking.googleapis.com")
            .reservedPeeringRanges(apigeeRange.name())
            .build());

        var org = new Organization("org", OrganizationArgs.builder()
            .analyticsRegion("us-central1")
            .projectId(current.project())
            .authorizedNetwork(apigeeNetwork.id())
            .build(), CustomResourceOptions.builder()
                .dependsOn(apigeeVpcConnection)
                .build());

    }
}
resources:
  apigeeNetwork:
    type: gcp:compute:Network
    name: apigee_network
    properties:
      name: apigee-network
  apigeeRange:
    type: gcp:compute:GlobalAddress
    name: apigee_range
    properties:
      name: apigee-range
      purpose: VPC_PEERING
      addressType: INTERNAL
      prefixLength: 16
      network: ${apigeeNetwork.id}
  apigeeVpcConnection:
    type: gcp:servicenetworking:Connection
    name: apigee_vpc_connection
    properties:
      network: ${apigeeNetwork.id}
      service: servicenetworking.googleapis.com
      reservedPeeringRanges:
        - ${apigeeRange.name}
  org:
    type: gcp:apigee:Organization
    properties:
      analyticsRegion: us-central1
      projectId: ${current.project}
      authorizedNetwork: ${apigeeNetwork.id}
    options:
      dependsOn:
        - ${apigeeVpcConnection}
variables:
  current:
    fn::invoke:
      function: gcp:organizations:getClientConfig
      arguments: {}

The authorizedNetwork property specifies which VPC network Apigee should peer with. Service Networking establishes the connection using a reserved IP range (apigeeRange), and the dependsOn ensures the VPC connection completes before Apigee provisions the organization. This enables private connectivity between Apigee runtime instances and resources in your VPC.

Create an organization without VPC peering

Some deployments use Private Google Access or don’t require private connectivity during initial setup.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const current = gcp.organizations.getClientConfig({});
const org = new gcp.apigee.Organization("org", {
    description: "Terraform-provisioned basic Apigee Org without VPC Peering.",
    analyticsRegion: "us-central1",
    projectId: current.then(current => current.project),
    disableVpcPeering: true,
});
import pulumi
import pulumi_gcp as gcp

current = gcp.organizations.get_client_config()
org = gcp.apigee.Organization("org",
    description="Terraform-provisioned basic Apigee Org without VPC Peering.",
    analytics_region="us-central1",
    project_id=current.project,
    disable_vpc_peering=True)
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/apigee"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		current, err := organizations.GetClientConfig(ctx, map[string]interface{}{}, nil)
		if err != nil {
			return err
		}
		_, err = apigee.NewOrganization(ctx, "org", &apigee.OrganizationArgs{
			Description:       pulumi.String("Terraform-provisioned basic Apigee Org without VPC Peering."),
			AnalyticsRegion:   pulumi.String("us-central1"),
			ProjectId:         pulumi.String(current.Project),
			DisableVpcPeering: pulumi.Bool(true),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var current = Gcp.Organizations.GetClientConfig.Invoke();

    var org = new Gcp.Apigee.Organization("org", new()
    {
        Description = "Terraform-provisioned basic Apigee Org without VPC Peering.",
        AnalyticsRegion = "us-central1",
        ProjectId = current.Apply(getClientConfigResult => getClientConfigResult.Project),
        DisableVpcPeering = true,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.apigee.Organization;
import com.pulumi.gcp.apigee.OrganizationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        final var current = OrganizationsFunctions.getClientConfig(%!v(PANIC=Format method: runtime error: invalid memory address or nil pointer dereference);

        var org = new Organization("org", OrganizationArgs.builder()
            .description("Terraform-provisioned basic Apigee Org without VPC Peering.")
            .analyticsRegion("us-central1")
            .projectId(current.project())
            .disableVpcPeering(true)
            .build());

    }
}
resources:
  org:
    type: gcp:apigee:Organization
    properties:
      description: Terraform-provisioned basic Apigee Org without VPC Peering.
      analyticsRegion: us-central1
      projectId: ${current.project}
      disableVpcPeering: true
variables:
  current:
    fn::invoke:
      function: gcp:organizations:getClientConfig
      arguments: {}

Setting disableVpcPeering to true provisions the organization without VPC network dependencies. The analyticsRegion determines where Apigee stores analytics data, and projectId associates the organization with your GCP project. This configuration is simpler but limits private connectivity options.

Configure data residency for regulatory compliance

Organizations subject to data sovereignty requirements can specify where Apigee stores control plane data.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const current = gcp.organizations.getClientConfig({});
const org = new gcp.apigee.Organization("org", {
    description: "Terraform-provisioned basic Apigee Org under European Union hosting jurisdiction.",
    projectId: current.then(current => current.project),
    apiConsumerDataLocation: "europe-west1",
    billingType: "PAYG",
    disableVpcPeering: true,
});
import pulumi
import pulumi_gcp as gcp

current = gcp.organizations.get_client_config()
org = gcp.apigee.Organization("org",
    description="Terraform-provisioned basic Apigee Org under European Union hosting jurisdiction.",
    project_id=current.project,
    api_consumer_data_location="europe-west1",
    billing_type="PAYG",
    disable_vpc_peering=True)
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/apigee"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		current, err := organizations.GetClientConfig(ctx, map[string]interface{}{}, nil)
		if err != nil {
			return err
		}
		_, err = apigee.NewOrganization(ctx, "org", &apigee.OrganizationArgs{
			Description:             pulumi.String("Terraform-provisioned basic Apigee Org under European Union hosting jurisdiction."),
			ProjectId:               pulumi.String(current.Project),
			ApiConsumerDataLocation: pulumi.String("europe-west1"),
			BillingType:             pulumi.String("PAYG"),
			DisableVpcPeering:       pulumi.Bool(true),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var current = Gcp.Organizations.GetClientConfig.Invoke();

    var org = new Gcp.Apigee.Organization("org", new()
    {
        Description = "Terraform-provisioned basic Apigee Org under European Union hosting jurisdiction.",
        ProjectId = current.Apply(getClientConfigResult => getClientConfigResult.Project),
        ApiConsumerDataLocation = "europe-west1",
        BillingType = "PAYG",
        DisableVpcPeering = true,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.apigee.Organization;
import com.pulumi.gcp.apigee.OrganizationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        final var current = OrganizationsFunctions.getClientConfig(%!v(PANIC=Format method: runtime error: invalid memory address or nil pointer dereference);

        var org = new Organization("org", OrganizationArgs.builder()
            .description("Terraform-provisioned basic Apigee Org under European Union hosting jurisdiction.")
            .projectId(current.project())
            .apiConsumerDataLocation("europe-west1")
            .billingType("PAYG")
            .disableVpcPeering(true)
            .build());

    }
}
resources:
  org:
    type: gcp:apigee:Organization
    properties:
      description: Terraform-provisioned basic Apigee Org under European Union hosting jurisdiction.
      projectId: ${current.project}
      apiConsumerDataLocation: europe-west1
      billingType: PAYG
      disableVpcPeering: true
variables:
  current:
    fn::invoke:
      function: gcp:organizations:getClientConfig
      arguments: {}

The apiConsumerDataLocation property controls which single region Apigee uses for control plane data storage. Setting it to “europe-west1” ensures data remains within European Union jurisdiction. The billingType must be “PAYG” (pay-as-you-go) for non-default data residency regions.

Encrypt runtime data with customer-managed keys

Enterprises with strict security policies often require customer-managed encryption keys for data at rest.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const current = gcp.organizations.getClientConfig({});
const apigeeNetwork = new gcp.compute.Network("apigee_network", {name: "apigee-network"});
const apigeeRange = new gcp.compute.GlobalAddress("apigee_range", {
    name: "apigee-range",
    purpose: "VPC_PEERING",
    addressType: "INTERNAL",
    prefixLength: 16,
    network: apigeeNetwork.id,
});
const apigeeVpcConnection = new gcp.servicenetworking.Connection("apigee_vpc_connection", {
    network: apigeeNetwork.id,
    service: "servicenetworking.googleapis.com",
    reservedPeeringRanges: [apigeeRange.name],
});
const apigeeKeyring = new gcp.kms.KeyRing("apigee_keyring", {
    name: "apigee-keyring",
    location: "us-central1",
});
const apigeeKey = new gcp.kms.CryptoKey("apigee_key", {
    name: "apigee-key",
    keyRing: apigeeKeyring.id,
});
const apigeeSa = new gcp.projects.ServiceIdentity("apigee_sa", {
    project: project.projectId,
    service: apigee.service,
});
const apigeeSaKeyuser = new gcp.kms.CryptoKeyIAMMember("apigee_sa_keyuser", {
    cryptoKeyId: apigeeKey.id,
    role: "roles/cloudkms.cryptoKeyEncrypterDecrypter",
    member: apigeeSa.member,
});
const org = new gcp.apigee.Organization("org", {
    analyticsRegion: "us-central1",
    displayName: "apigee-org",
    description: "Auto-provisioned Apigee Org.",
    projectId: current.then(current => current.project),
    authorizedNetwork: apigeeNetwork.id,
    runtimeDatabaseEncryptionKeyName: apigeeKey.id,
}, {
    dependsOn: [
        apigeeVpcConnection,
        apigeeSaKeyuser,
    ],
});
import pulumi
import pulumi_gcp as gcp

current = gcp.organizations.get_client_config()
apigee_network = gcp.compute.Network("apigee_network", name="apigee-network")
apigee_range = gcp.compute.GlobalAddress("apigee_range",
    name="apigee-range",
    purpose="VPC_PEERING",
    address_type="INTERNAL",
    prefix_length=16,
    network=apigee_network.id)
apigee_vpc_connection = gcp.servicenetworking.Connection("apigee_vpc_connection",
    network=apigee_network.id,
    service="servicenetworking.googleapis.com",
    reserved_peering_ranges=[apigee_range.name])
apigee_keyring = gcp.kms.KeyRing("apigee_keyring",
    name="apigee-keyring",
    location="us-central1")
apigee_key = gcp.kms.CryptoKey("apigee_key",
    name="apigee-key",
    key_ring=apigee_keyring.id)
apigee_sa = gcp.projects.ServiceIdentity("apigee_sa",
    project=project["projectId"],
    service=apigee["service"])
apigee_sa_keyuser = gcp.kms.CryptoKeyIAMMember("apigee_sa_keyuser",
    crypto_key_id=apigee_key.id,
    role="roles/cloudkms.cryptoKeyEncrypterDecrypter",
    member=apigee_sa.member)
org = gcp.apigee.Organization("org",
    analytics_region="us-central1",
    display_name="apigee-org",
    description="Auto-provisioned Apigee Org.",
    project_id=current.project,
    authorized_network=apigee_network.id,
    runtime_database_encryption_key_name=apigee_key.id,
    opts = pulumi.ResourceOptions(depends_on=[
            apigee_vpc_connection,
            apigee_sa_keyuser,
        ]))
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/apigee"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/kms"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/projects"
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/servicenetworking"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		current, err := organizations.GetClientConfig(ctx, map[string]interface{}{}, nil)
		if err != nil {
			return err
		}
		apigeeNetwork, err := compute.NewNetwork(ctx, "apigee_network", &compute.NetworkArgs{
			Name: pulumi.String("apigee-network"),
		})
		if err != nil {
			return err
		}
		apigeeRange, err := compute.NewGlobalAddress(ctx, "apigee_range", &compute.GlobalAddressArgs{
			Name:         pulumi.String("apigee-range"),
			Purpose:      pulumi.String("VPC_PEERING"),
			AddressType:  pulumi.String("INTERNAL"),
			PrefixLength: pulumi.Int(16),
			Network:      apigeeNetwork.ID(),
		})
		if err != nil {
			return err
		}
		apigeeVpcConnection, err := servicenetworking.NewConnection(ctx, "apigee_vpc_connection", &servicenetworking.ConnectionArgs{
			Network: apigeeNetwork.ID(),
			Service: pulumi.String("servicenetworking.googleapis.com"),
			ReservedPeeringRanges: pulumi.StringArray{
				apigeeRange.Name,
			},
		})
		if err != nil {
			return err
		}
		apigeeKeyring, err := kms.NewKeyRing(ctx, "apigee_keyring", &kms.KeyRingArgs{
			Name:     pulumi.String("apigee-keyring"),
			Location: pulumi.String("us-central1"),
		})
		if err != nil {
			return err
		}
		apigeeKey, err := kms.NewCryptoKey(ctx, "apigee_key", &kms.CryptoKeyArgs{
			Name:    pulumi.String("apigee-key"),
			KeyRing: apigeeKeyring.ID(),
		})
		if err != nil {
			return err
		}
		apigeeSa, err := projects.NewServiceIdentity(ctx, "apigee_sa", &projects.ServiceIdentityArgs{
			Project: pulumi.Any(project.ProjectId),
			Service: pulumi.Any(apigee.Service),
		})
		if err != nil {
			return err
		}
		apigeeSaKeyuser, err := kms.NewCryptoKeyIAMMember(ctx, "apigee_sa_keyuser", &kms.CryptoKeyIAMMemberArgs{
			CryptoKeyId: apigeeKey.ID(),
			Role:        pulumi.String("roles/cloudkms.cryptoKeyEncrypterDecrypter"),
			Member:      apigeeSa.Member,
		})
		if err != nil {
			return err
		}
		_, err = apigee.NewOrganization(ctx, "org", &apigee.OrganizationArgs{
			AnalyticsRegion:                  pulumi.String("us-central1"),
			DisplayName:                      pulumi.String("apigee-org"),
			Description:                      pulumi.String("Auto-provisioned Apigee Org."),
			ProjectId:                        pulumi.String(current.Project),
			AuthorizedNetwork:                apigeeNetwork.ID(),
			RuntimeDatabaseEncryptionKeyName: apigeeKey.ID(),
		}, pulumi.DependsOn([]pulumi.Resource{
			apigeeVpcConnection,
			apigeeSaKeyuser,
		}))
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var current = Gcp.Organizations.GetClientConfig.Invoke();

    var apigeeNetwork = new Gcp.Compute.Network("apigee_network", new()
    {
        Name = "apigee-network",
    });

    var apigeeRange = new Gcp.Compute.GlobalAddress("apigee_range", new()
    {
        Name = "apigee-range",
        Purpose = "VPC_PEERING",
        AddressType = "INTERNAL",
        PrefixLength = 16,
        Network = apigeeNetwork.Id,
    });

    var apigeeVpcConnection = new Gcp.ServiceNetworking.Connection("apigee_vpc_connection", new()
    {
        Network = apigeeNetwork.Id,
        Service = "servicenetworking.googleapis.com",
        ReservedPeeringRanges = new[]
        {
            apigeeRange.Name,
        },
    });

    var apigeeKeyring = new Gcp.Kms.KeyRing("apigee_keyring", new()
    {
        Name = "apigee-keyring",
        Location = "us-central1",
    });

    var apigeeKey = new Gcp.Kms.CryptoKey("apigee_key", new()
    {
        Name = "apigee-key",
        KeyRing = apigeeKeyring.Id,
    });

    var apigeeSa = new Gcp.Projects.ServiceIdentity("apigee_sa", new()
    {
        Project = project.ProjectId,
        Service = apigee.Service,
    });

    var apigeeSaKeyuser = new Gcp.Kms.CryptoKeyIAMMember("apigee_sa_keyuser", new()
    {
        CryptoKeyId = apigeeKey.Id,
        Role = "roles/cloudkms.cryptoKeyEncrypterDecrypter",
        Member = apigeeSa.Member,
    });

    var org = new Gcp.Apigee.Organization("org", new()
    {
        AnalyticsRegion = "us-central1",
        DisplayName = "apigee-org",
        Description = "Auto-provisioned Apigee Org.",
        ProjectId = current.Apply(getClientConfigResult => getClientConfigResult.Project),
        AuthorizedNetwork = apigeeNetwork.Id,
        RuntimeDatabaseEncryptionKeyName = apigeeKey.Id,
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            apigeeVpcConnection,
            apigeeSaKeyuser,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.compute.Network;
import com.pulumi.gcp.compute.NetworkArgs;
import com.pulumi.gcp.compute.GlobalAddress;
import com.pulumi.gcp.compute.GlobalAddressArgs;
import com.pulumi.gcp.servicenetworking.Connection;
import com.pulumi.gcp.servicenetworking.ConnectionArgs;
import com.pulumi.gcp.kms.KeyRing;
import com.pulumi.gcp.kms.KeyRingArgs;
import com.pulumi.gcp.kms.CryptoKey;
import com.pulumi.gcp.kms.CryptoKeyArgs;
import com.pulumi.gcp.projects.ServiceIdentity;
import com.pulumi.gcp.projects.ServiceIdentityArgs;
import com.pulumi.gcp.kms.CryptoKeyIAMMember;
import com.pulumi.gcp.kms.CryptoKeyIAMMemberArgs;
import com.pulumi.gcp.apigee.Organization;
import com.pulumi.gcp.apigee.OrganizationArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        final var current = OrganizationsFunctions.getClientConfig(%!v(PANIC=Format method: runtime error: invalid memory address or nil pointer dereference);

        var apigeeNetwork = new Network("apigeeNetwork", NetworkArgs.builder()
            .name("apigee-network")
            .build());

        var apigeeRange = new GlobalAddress("apigeeRange", GlobalAddressArgs.builder()
            .name("apigee-range")
            .purpose("VPC_PEERING")
            .addressType("INTERNAL")
            .prefixLength(16)
            .network(apigeeNetwork.id())
            .build());

        var apigeeVpcConnection = new Connection("apigeeVpcConnection", ConnectionArgs.builder()
            .network(apigeeNetwork.id())
            .service("servicenetworking.googleapis.com")
            .reservedPeeringRanges(apigeeRange.name())
            .build());

        var apigeeKeyring = new KeyRing("apigeeKeyring", KeyRingArgs.builder()
            .name("apigee-keyring")
            .location("us-central1")
            .build());

        var apigeeKey = new CryptoKey("apigeeKey", CryptoKeyArgs.builder()
            .name("apigee-key")
            .keyRing(apigeeKeyring.id())
            .build());

        var apigeeSa = new ServiceIdentity("apigeeSa", ServiceIdentityArgs.builder()
            .project(project.projectId())
            .service(apigee.service())
            .build());

        var apigeeSaKeyuser = new CryptoKeyIAMMember("apigeeSaKeyuser", CryptoKeyIAMMemberArgs.builder()
            .cryptoKeyId(apigeeKey.id())
            .role("roles/cloudkms.cryptoKeyEncrypterDecrypter")
            .member(apigeeSa.member())
            .build());

        var org = new Organization("org", OrganizationArgs.builder()
            .analyticsRegion("us-central1")
            .displayName("apigee-org")
            .description("Auto-provisioned Apigee Org.")
            .projectId(current.project())
            .authorizedNetwork(apigeeNetwork.id())
            .runtimeDatabaseEncryptionKeyName(apigeeKey.id())
            .build(), CustomResourceOptions.builder()
                .dependsOn(                
                    apigeeVpcConnection,
                    apigeeSaKeyuser)
                .build());

    }
}
resources:
  apigeeNetwork:
    type: gcp:compute:Network
    name: apigee_network
    properties:
      name: apigee-network
  apigeeRange:
    type: gcp:compute:GlobalAddress
    name: apigee_range
    properties:
      name: apigee-range
      purpose: VPC_PEERING
      addressType: INTERNAL
      prefixLength: 16
      network: ${apigeeNetwork.id}
  apigeeVpcConnection:
    type: gcp:servicenetworking:Connection
    name: apigee_vpc_connection
    properties:
      network: ${apigeeNetwork.id}
      service: servicenetworking.googleapis.com
      reservedPeeringRanges:
        - ${apigeeRange.name}
  apigeeKeyring:
    type: gcp:kms:KeyRing
    name: apigee_keyring
    properties:
      name: apigee-keyring
      location: us-central1
  apigeeKey:
    type: gcp:kms:CryptoKey
    name: apigee_key
    properties:
      name: apigee-key
      keyRing: ${apigeeKeyring.id}
  apigeeSa:
    type: gcp:projects:ServiceIdentity
    name: apigee_sa
    properties:
      project: ${project.projectId}
      service: ${apigee.service}
  apigeeSaKeyuser:
    type: gcp:kms:CryptoKeyIAMMember
    name: apigee_sa_keyuser
    properties:
      cryptoKeyId: ${apigeeKey.id}
      role: roles/cloudkms.cryptoKeyEncrypterDecrypter
      member: ${apigeeSa.member}
  org:
    type: gcp:apigee:Organization
    properties:
      analyticsRegion: us-central1
      displayName: apigee-org
      description: Auto-provisioned Apigee Org.
      projectId: ${current.project}
      authorizedNetwork: ${apigeeNetwork.id}
      runtimeDatabaseEncryptionKeyName: ${apigeeKey.id}
    options:
      dependsOn:
        - ${apigeeVpcConnection}
        - ${apigeeSaKeyuser}
variables:
  current:
    fn::invoke:
      function: gcp:organizations:getClientConfig
      arguments: {}

The runtimeDatabaseEncryptionKeyName property references a Cloud KMS crypto key that encrypts data stored across runtime instances. The Apigee service identity needs the cryptoKeyEncrypterDecrypter role on the key, and dependsOn ensures both VPC connection and KMS permissions exist before organization creation. This gives you control over key rotation and access policies.

Beyond these examples

These snippets focus on specific organization-level features: VPC connectivity and Service Networking integration, data residency and regional compliance, and customer-managed encryption with Cloud KMS. They’re intentionally minimal rather than full Apigee deployments.

The examples may reference pre-existing infrastructure such as GCP project with Apigee API enabled, VPC networks, global address ranges, Service Networking connections, and KMS key rings, crypto keys, and IAM service identities. They focus on configuring the organization rather than provisioning everything around it.

To keep things focused, common organization patterns are omitted, including:

  • Control plane encryption (controlPlaneEncryptionKeyName)
  • API consumer data encryption (apiConsumerDataEncryptionKeyName)
  • Organization properties and custom metadata
  • Hybrid runtime type configuration
  • Retention policies for soft-deleted organizations

These omissions are intentional: the goal is to illustrate how each organization feature is wired, not provide drop-in API management modules. See the Apigee Organization resource reference for all available configuration options.

Let's create GCP Apigee Organizations

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

VPC Peering & Networking
Do I need to set up VPC peering for my Apigee organization?
No, VPC peering is optional. You can disable it by setting disableVpcPeering to true. If you don’t provide an authorizedNetwork, you must set disableVpcPeering to true.
How do I set up VPC peering for my Apigee organization?
Create a VPC network, reserve a global address with purpose: "VPC_PEERING", establish a servicenetworking.Connection, then reference the network in authorizedNetwork. Use dependsOn to ensure the connection exists before creating the organization.
Can I change VPC settings after creating runtime instances?
No, both authorizedNetwork and disableVpcPeering can only be updated when there are no runtime instances. You must remove all runtime instances before changing these settings.
Why do the examples use dependsOn with the VPC connection?
The dependsOn ensures the VPC peering connection is fully established before creating the Apigee organization, preventing creation failures due to missing network dependencies.
Encryption & Security
What encryption options are available for Apigee organizations?

You can configure three types of encryption with Cloud KMS keys:

  1. Runtime database - runtimeDatabaseEncryptionKeyName encrypts data stored across runtime instances
  2. Control plane - controlPlaneEncryptionKeyName encrypts control plane data in multi-region storage (US/EU only)
  3. API consumer data - apiConsumerDataEncryptionKeyName encrypts API consumer data

If not specified, Google-Managed encryption is used.

How do I set up KMS encryption for my Apigee organization?
Create a KMS KeyRing and CryptoKey, create a service identity for Apigee, grant it the roles/cloudkms.cryptoKeyEncrypterDecrypter role on the key, then reference the key in runtimeDatabaseEncryptionKeyName. Use dependsOn to ensure IAM permissions are set before creating the organization.
Can I change encryption keys after creating the organization?
No, all encryption key properties (runtimeDatabaseEncryptionKeyName, controlPlaneEncryptionKeyName, apiConsumerDataEncryptionKeyName) are immutable and cannot be updated after organization creation.
Data Residency & Regions
How do I configure data residency for the European Union?
Set apiConsumerDataLocation to a European region like "europe-west1", specify billingType as "PAYG", and set disableVpcPeering to true.
When do I need to set apiConsumerDataLocation?
Only when using non-default data residency regions. This field determines which single region Apigee uses to store control plane data.
Immutability & Configuration
What properties can't be changed after creating the organization?
The following properties are immutable: billingType, projectId, analyticsRegion, apiConsumerDataLocation, apiConsumerDataEncryptionKeyName, controlPlaneEncryptionKeyName, runtimeDatabaseEncryptionKeyName, and runtimeType.
What's the default runtime type for Apigee organizations?
The default runtimeType is CLOUD. You can also specify HYBRID based on your Apigee subscription.
How long is data retained after deleting an organization?
For soft-deleted organizations (non-EVALUATION billing types), the retention setting controls how long data is kept. During this period, the organization can be restored. The default is DELETION_RETENTION_UNSPECIFIED.

Using a different cloud?

Explore integration guides for other cloud providers: