Learning Goal: Learn multiple ways to interact with your ConnectRPC service and generate client SDKs.
Time: ~20 minutes
In this part, you'll learn:
- How to call your API using HTTP/JSON with
curl - How to call your API using gRPC with
grpcurl - How to generate TypeScript and Go SDKs
- How to generate an OpenAPI specification
- How to use the generated SDKs in your applications
One of the key benefits of ConnectRPC is protocol flexibility. The same service can be consumed via:
- HTTP/JSON - Simple REST-like calls using curl or any HTTP client
- gRPC - High-performance binary protocol
- Typed SDKs - Generated client libraries with full type safety
- OpenAPI - Standard API documentation format
From the API consumer's perspective, GraphQL is no longer part of the picture. The API behaves like a conventional gRPC or HTTP service with well-defined request and response contracts.
The simplest way to interact with your API is using HTTP/JSON requests.
Retrieve all employees:
curl -X POST http://localhost:5026/employees.v1.HrService/GetEmployees \
-H "Content-Type: application/json" \
-H "Connect-Protocol-Version: 1" \
-d '{}'The same query using GET (enabled by the NO_SIDE_EFFECTS option):
curl --get \
--data-urlencode 'encoding=json' \
--data-urlencode 'message={}' \
--data-urlencode 'connect=v1' \
http://localhost:5026/employees.v1.HrService/GetEmployeesWhy GET matters: GET requests can be cached by CDNs and browsers, improving performance for read operations.
Retrieve a specific employee:
curl -X POST http://localhost:5026/employees.v1.HrService/GetEmployeeById \
-H "Content-Type: application/json" \
-H "Connect-Protocol-Version: 1" \
-d '{"id": 1}'curl --get \
--data-urlencode 'encoding=json' \
--data-urlencode 'message={"id": 1}' \
--data-urlencode 'connect=v1' \
http://localhost:5026/employees.v1.HrService/GetEmployeeByIdUpdate an employee's mood:
curl -X POST http://localhost:5026/employees.v1.HrService/UpdateEmployeeMood \
-H "Content-Type: application/json" \
-H "Connect-Protocol-Version: 1" \
-d '{"id": 1, "mood": "MOOD_HAPPY"}'Note: Mutations only support POST (not GET) because they have side effects.
For gRPC clients, you can use grpcurl to interact with your service.
grpcurl -plaintext \
-proto ./services/service.proto \
-d '{}' \
localhost:5026 \
employees.v1.HrService/GetEmployeesgrpcurl -plaintext \
-proto ./services/service.proto \
-d '{"id": 1}' \
localhost:5026 \
employees.v1.HrService/GetEmployeeByIdgrpcurl -plaintext \
-proto ./services/service.proto \
-d '{"id": 1, "mood": "MOOD_HAPPY"}' \
localhost:5026 \
employees.v1.HrService/UpdateEmployeeMoodCommand breakdown:
-plaintext- Use unencrypted connection (for local development)-proto- Path to your proto file-d- Request data in JSON formatlocalhost:5026- Server addressemployees.v1.HrService/GetEmployees- Fully qualified method name
To generate client SDKs and OpenAPI specifications, you'll use Buf, a modern tool for working with Protocol Buffers.
Install the required tools:
# Install Buf CLI
brew install bufbuild/buf/buf
# Install Go plugins for Go SDK generation
go install connectrpc.com/connect/cmd/protoc-gen-connect-go@latest
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
# Install TypeScript/JavaScript plugins for TypeScript SDK generation
npm install --save-dev @bufbuild/protoc-gen-es @connectrpc/protoc-gen-connect-es
# Install OpenAPI plugin
go install connectrpc.com/connect/cmd/protoc-gen-connect-openapi@latestEnsure the Go bin directory is in your PATH:
export PATH="$PATH:$(go env GOPATH)/bin"This project includes two Buf configuration files:
buf.yaml - Configures the Buf module:
- Defines the module name and path
- Excludes
node_modulesfrom processing - Enables standard linting rules to ensure proto file quality
- Configures breaking change detection to maintain API compatibility
buf.gen.yaml - Configures code generation:
- Managed mode: Automatically manages Go package paths
- Go SDK plugins: Generates Go client and server stubs
- TypeScript SDK plugins: Generates TypeScript client code
- OpenAPI plugin: Generates OpenAPI specification
- All outputs are organized into the
gen/directory by type
Generate TypeScript SDK, Go SDK, and OpenAPI specification with a single command:
buf generateBuf will automatically discover the proto files in your module and generate all outputs.
Generated files:
- Go SDK:
gen/go/- Go client and server stubs - TypeScript SDK:
gen/ts/- TypeScript client code - OpenAPI:
gen/openapi/- OpenAPI specification
cat gen/openapi/service.openapi.yamlThe OpenAPI spec describes all your RPC methods as HTTP endpoints, making it easy to:
- Import into API documentation tools (Swagger UI, Redoc, etc.)
- Generate client SDKs in various languages
- Share API contracts with external teams
- Test APIs using OpenAPI-compatible tools
npm install @connectrpc/connect @connectrpc/connect-webimport { createPromiseClient } from "@connectrpc/connect";
import { createConnectTransport } from "@connectrpc/connect-web";
import { HrService } from "./gen/ts/service_connect";
// Create a transport
const transport = createConnectTransport({
baseUrl: "http://localhost:5026",
});
// Create a client
const client = createPromiseClient(HrService, transport);
// Call the API
const response = await client.getEmployeeById({ id: 1 });
console.log(response.employee);Benefits:
- ✅ Full TypeScript type safety
- ✅ Autocomplete in your IDE
- ✅ Compile-time error checking
- ✅ No need to write request/response types manually
go get connectrpc.com/connectpackage main
import (
"context"
"fmt"
"log"
"net/http"
"connectrpc.com/connect"
employeesv1 "github.com/wundergraph/connectrpc-tutorial/gen/go/employees/v1"
"github.com/wundergraph/connectrpc-tutorial/gen/go/employees/v1/employeesv1connect"
)
func main() {
client := employeesv1connect.NewHrServiceClient(
http.DefaultClient,
"http://localhost:5026",
)
req := connect.NewRequest(&employeesv1.GetEmployeeByIdRequest{
Id: 1,
})
res, err := client.GetEmployeeById(context.Background(), req)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Employee: %+v\n", res.Msg.Employee)
}Benefits:
- ✅ Strongly typed Go structs
- ✅ Compile-time type checking
- ✅ Idiomatic Go error handling
- ✅ High performance with gRPC protocol support
Whenever you modify your GraphQL operations or regenerate your proto files, simply run:
buf generateThis ensures your SDKs stay in sync with your API contract.
Workflow:
- Update GraphQL operations in
services/*.graphql - Regenerate proto:
wgc grpc-service generate ... - Regenerate SDKs:
buf generate - Restart the router to pick up changes
Checklist:
- You can call the API using
curl(HTTP/JSON) - You can call the API using
grpcurl(gRPC) - You have generated TypeScript SDK in
gen/ts/ - You have generated Go SDK in
gen/go/ - You have generated OpenAPI spec in
gen/openapi/ - You understand how to keep SDKs in sync with your API
Verify generated files:
ls -R gen/You should see directories for go/, ts/, and openapi/.
✅ How to consume your API using HTTP/JSON with curl
✅ How to consume your API using gRPC with grpcurl
✅ The difference between GET and POST for queries
✅ How to use Buf to generate client SDKs
✅ How to generate OpenAPI specifications
✅ How to use TypeScript and Go SDKs in your applications
✅ How to keep SDKs in sync with your API contract
Congratulations! You've successfully:
- ✅ Converted GraphQL operations into Protocol Buffer definitions
- ✅ Run a ConnectRPC server using the Cosmo Router
- ✅ Consumed the same API via multiple protocols
- ✅ Generated strongly typed SDKs for TypeScript and Go
- ✅ Generated an OpenAPI specification
For API Producers:
- You can expose GraphQL APIs to non-GraphQL consumers without rewriting resolvers
- Trusted Documents provide stable API contracts that can be versioned
- The router handles all protocol translation automatically
For API Consumers:
- You can use familiar tools and protocols (HTTP, gRPC, typed SDKs)
- You get full type safety without learning GraphQL
- The same API surface works across multiple languages and platforms
- Explore adding more operations to your service
- Try generating SDKs for other languages using Buf plugins
- Integrate the generated SDKs into your applications
- Set up CI/CD to automatically regenerate SDKs when operations change
- Explore versioning strategies for your proto definitions
- 📚 Cosmo Documentation
- 📚 ConnectRPC Documentation
- 📚 Buf Documentation
- 💬 WunderGraph Community
- 🐛 Report an Issue
Navigation: