DEV Community

Cover image for Apigee Handbook on GCP: Quick Start Guide for starting
Bryan Granado
Bryan Granado

Posted on

Apigee Handbook on GCP: Quick Start Guide for starting

Has your DevOps or Platform Engineering team just handed you access to an Apigee organization in Google Cloud (GCP) and said, “You’re good to deploy your APIs”? If you opened the console and wondered where to start, this post is for you.

We’re not going to talk about VPC peering or instance provisioning (DevOps already handled that and it costs money). We’ll focus on what matters to you as a Developer: how to take that infrastructure “shell” and turn it into a secure, optimized, and functional gateway for your microservices.

1. High-level overview: where you stand

Apigee is an API Management platform. Think of it as an “Intelligent Receptionist” standing in front of your servers (the backend).

When DevOps configures the environment, they usually provide you with a default domain. Typically the invocation URL looks like:

https://{org-name}-{environment}.apigee.net

Or, if they set up a custom domain:
https://api.yourcompany.com

Your job is not to configure that domain; your job is to define what happens after the request reaches that URL.


2. What is an API Proxy?

The fundamental building block in Apigee is the API Proxy.

Think of it as a façade. The client (a mobile app, web app) never speaks directly to your backend (Cloud Run, GKE, VM). It speaks with the Proxy.

A Proxy lets you:

  1. Decouple: Change your backend implementation (Java → Go, VM → Serverless) while keeping the public Proxy URL stable.
  2. Secure: Validate tokens (OAuth, API Keys) before traffic reaches your backend.
  3. Transform: Accept XML and return JSON without touching backend code.

3. Anatomy of a Proxy: Endpoint vs Target

This is where many get confused. A Proxy has two worlds:

A. Proxy Endpoint (the face to the client)

This defines how the outside world consumes your API. Here you define:

  • The Base Path (e.g., /v1/users).
  • Security rules (who can enter).
  • What happens before the request goes to the backend.

B. Target Endpoint (the connection to the backend)

This defines where Apigee fetches the data. Here you define:

  • The URL of your backend service.
  • SSL/TLS settings.
  • What happens when the backend responds.

Didactic note: The flow is:
Client -> Proxy Endpoint -> (logic) -> Target Endpoint -> Backend


4. Creating your first Proxy: Default vs Optimized

The “Default” way (Console UI)

For learning, the GCP Console is great.

  1. Go to Apigee > Proxies > Create New.
  2. Select Reverse Proxy.
  3. Fill in:
    • Name: user-service-v1
    • Base Path: /v1/users
    • Target (Backend): https://my-backend-on-cloudrun.app
  4. Deploy. This generates a basic XML. It works, but for production you want more control.

The “Optimized” way (Development best practices)

A better professional approach is to avoid editing XML directly in the web console (it’s error-prone and hard to version). Instead, develop locally (VS Code + Apigee extension) and upload the bundle.
Because this post is for beginners, here’s a link that dives deeper:

docs


5. Environment variables: TargetServers and KVMs

This is where you collaborate with DevOps. Environments cost money; you don’t want a separate Proxy per environment.

A well-configured Target Endpoint should NOT hardcode a backend URL like this:

<HTTPTargetConnection>
    <URL>https://my-backend-dev.com</URL>
</HTTPTargetConnection>
Enter fullscreen mode Exit fullscreen mode

What is a TargetServer?
A TargetServer is a named variable at environment level.

In DEV, the TargetServer named my-backend-server points to dev.backend.com (Cloud Run, VM, etc).

Your task: Ask DevOps to create the TargetServer for each environment (or create it yourself if you have permissions). Then reference the TargetServer by name in your XML.


6. Flows and Match Rules: the Proxy brain

A Proxy isn't an empty tube; it makes decisions. That’s implemented using Flows.

The execution flow inside an endpoint (Proxy or Target) follows this order:

PreFlow: Always runs. Put global logic here (e.g., traffic protection, API Key validation).

Conditional Flows: Run only if a condition (Match) applies.

PostFlow: Always runs at the end (e.g., transaction logging).

Configuring Conditional Flows with Matches

Suppose your API exposes:

GET /users (List)

POST /users (Create)

You might not want the same rules for both (POST may require stricter validation). Use <Condition>.

Example:

<Flow name="/CreateUser post">
  <Description>Logic for creating users</Description>
  <Condition>(proxy.pathsuffix MatchesPath "/users") and (request.verb = "POST")</Condition>

  <Request>
    <Step>
      <Name>Validate-JSON-Input</Name>
    </Step>
  </Request>
</Flow>
Enter fullscreen mode Exit fullscreen mode

A more complete example:

<ProxyEndpoint name="default">
  <PreFlow name="PreFlow">
    <Request>
      <Step><Name>Verify-API-Key</Name></Step>
    </Request>
  </PreFlow>

  <Flow name="CreateResource">
    <Condition>(request.verb = "POST")</Condition>
    <Request>
      <Step><Name>Quota-Check</Name></Step>
    </Request>
  </Flow>

  <PostFlow name="PostFlow">
    <Response>
      <Step><Name>Remove-Internal-Headers</Name></Step>
    </Response>
  </PostFlow>
</ProxyEndpoint>
Enter fullscreen mode Exit fullscreen mode

Context and flow variables

Apigee is “context aware”: everything passing through the proxy generates variables you can read in conditions:

  • request.header.Content-Type — to know the incoming payload type.
  • response.status.code — to detect backend failures.
  • developer.app.name — to identify the calling app.

This helps you implement defensive logic. If the backend returns 500, you don’t want to expose the backend stack trace; you can return a suitable response instead.

Example:

<Condition>
  (response.status.code = 500)
</Condition>
Enter fullscreen mode Exit fullscreen mode

Policies

Policies are configurations that control parts of the flow. Apigee provides many built-in policies, and you configure them via XML and attach them to steps in flows.

Common policies:

  • Verify API Key:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<VerifyAPIKey async="false" continueOnError="false" enabled="true" name="Verify-API-Key-Policy">
  <APIKey ref="request.header.x-api-key"/>
</VerifyAPIKey>
Enter fullscreen mode Exit fullscreen mode
  • OAuthV2 (Verify Access Token):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OAuthV2 async="false" continueOnError="false" enabled="true" name="Verify-OAuth-Token-Policy">
  <Operation>VerifyAccessToken</Operation>
  <AccessToken prefix="Bearer">request.header.Authorization</AccessToken>
</OAuthV2>
Enter fullscreen mode Exit fullscreen mode
  • Access Control (IP-based filtering):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AccessControl async="false" continueOnError="false" enabled="true" name="Access-Control-Policy">
  <IPRules noRuleMatchAction="DENY">
    <Rule action="DENY" name="Block-Specific-IP">
      <SourceAddress mask="32">192.168.1.100</SourceAddress>
    </Rule>

    <Rule action="ALLOW" name="Allow-Internal-Network">
      <SourceAddress mask="24">10.0.0.0</SourceAddress>
    </Rule>
  </IPRules>

  <IPAddresses ref="client.ip"/>
</AccessControl>
Enter fullscreen mode Exit fullscreen mode

if you need more help with this, here found:


Great — if you got this far you now have a rapid-start checklist and the basic concepts to manage APIs in your Apigee environment.

I hope this helps.

I’m on Threads, LinkedIn and Instagram as brngranado. See you there for more content.

Top comments (0)