Add REST API endpoints to your Extend Event Handler app
Overview
Extend Event Handler apps can now expose REST API endpoints in addition to handling Kafka events. This uses the same gRPC Gateway stack as Extend Service Extension, which means a single Extend app can both react to AGS events and serve custom RESTful endpoints.
For example, you could build an Event Handler app that grants rewards when a player logs in (event-driven) while also exposing an admin REST endpoint to query reward history (request-driven).
This feature is available starting from the AGS 2026.2 release.
How it works
The Event Handler app already runs a gRPC server for receiving Kafka events. With REST API support, a gRPC Gateway is added to the stack:
- You define REST endpoint mappings in your protobuf file using
google.api.httpannotations, alongside your existing event handler service definitions. - At build time, the gRPC Gateway code and OpenAPI specification are generated from the protobuf.
- At runtime, the gRPC Gateway translates incoming HTTP requests into gRPC calls and forwards them to your gRPC server methods.
This is the same architecture used by Extend Service Extension. For a detailed diagram, see the Extend Service Extension overview.
Prerequisites
- You have completed the Event Handler getting started guide and are familiar with the Event Handler app template.
- You have cloned the REST-API-enabled Event Handler app template.
The REST-API-enabled Event Handler app templates are currently in development. Template repository links will be added here when they become available.
Define REST API endpoints in protobuf
Your protobuf file contains both event handler service definitions and REST endpoint definitions. To add REST endpoints, you annotate gRPC methods with google.api.http, permission, and OpenAPI options, just like in Extend Service Extension.
The following example shows a protobuf file that defines both an event handler method and a REST endpoint:
import "google/api/annotations.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "permission.proto";
// Event handler service for processing Kafka events
service EventHandlerService {
// This method is invoked by Kafka Connect when a UserLoggedIn event occurs
rpc OnUserLoggedIn (UserLoggedInEvent) returns (EventHandlerResponse);
}
// REST API service for custom endpoints
service RewardService {
rpc GetRewardHistory (GetRewardHistoryRequest) returns (GetRewardHistoryResponse) {
option (permission.action) = READ;
option (permission.resource) = "ADMIN:NAMESPACE:{namespace}:REWARD:HISTORY";
option (google.api.http) = {
get: "/v1/admin/namespace/{namespace}/rewards/history"
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Get reward history"
description: "Retrieve the history of rewards granted by the event handler"
security: {
security_requirement: {
key: "Bearer"
value: {}
}
}
};
}
}
message GetRewardHistoryRequest {
string namespace = 1;
}
message GetRewardHistoryResponse {
repeated RewardRecord records = 1;
}
message RewardRecord {
string user_id = 1;
string item_id = 2;
string granted_at = 3;
}
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
info: {
title: "Event Handler with REST API";
version: "1.0";
};
schemes: HTTP;
schemes: HTTPS;
base_path: "/service";
security_definitions: {
security: {
key: "Bearer";
value: {
type: TYPE_API_KEY;
in: IN_HEADER;
name: "Authorization";
}
}
};
};
The key annotations are:
-
option (google.api.http)— Maps a gRPC method to a RESTful endpoint. See the gRPC-Gateway documentation for details. -
option (permission.resource)andoption (permission.action)— Defines the required AGS permission to invoke the endpoint. The gRPC server interceptor uses these values to perform authorization. Valid actions areCREATE,READ,UPDATE, orDELETE. See AGS permission actions for details. -
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger)andoption (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation)— Provides metadata for generating the OpenAPI 2.0 specification. See the gRPC-Gateway OpenAPI documentation for details.
Generate stubs and gateway code
After modifying the protobuf file, regenerate the stubs and gateway code.
The commands below are based on the REST-API-enabled Event Handler app templates, which are currently in development. The exact commands may vary depending on the final template structure.
- C#
- Go
- Java
- Python
make proto # Generate gateway code and swagger JSON
make build # Some protobuf code is generated on-the-fly during build
make proto # Generate protobuf code, gateway code, and swagger JSON
make proto # Generate gateway code and swagger JSON
make build # Some protobuf code is generated on-the-fly during build
make proto # Generate protobuf code, gateway code, and swagger JSON
Always run the above commands after modifying the protobuf file to regenerate the stubs.
Implement request handlers
After generating the stubs, implement the gRPC service methods that back your REST endpoints. The implementation pattern is the same as Extend Service Extension. For detailed examples in each language, see Create your own Extend Service Extension app.
Your event handler methods and REST endpoint methods can coexist in the same app. The event handler methods are invoked by Kafka Connect, while the REST endpoint methods are invoked through the gRPC Gateway.
Test REST API endpoints
To test your REST endpoints locally, start the app and send HTTP requests to the gRPC Gateway port.
# Example: query reward history
curl -X GET "http://localhost:8000/service/v1/admin/namespace/mygame/rewards/history" \
-H "Authorization: Bearer <your-access-token>"
When PLUGIN_GRPC_SERVER_AUTH_ENABLED is set to true, the app requires a valid AGS access token with the appropriate permissions. Set it to false during local development to bypass authentication.
You can also use tools like Postman or any HTTP client. The auto-generated OpenAPI specification (Swagger JSON) is available in the app template and can be imported into these tools for convenience.
When to use Event Handler with REST API vs. Service Extension
Use Event Handler with REST API when your app needs both event-driven logic (reacting to AGS events through Kafka) and custom REST endpoints in a single deployment. Use Extend Service Extension when you only need custom REST endpoints without event handling.