A powerful Go tool that automatically generates Postman collections and environments by scanning your Go codebase for API endpoints.
- 🧠 Intelligent Project Analysis: Comprehensively analyzes entire Go projects to understand architecture patterns
- 🏗️ Architecture-Agnostic: Automatically detects and adapts to Clean Architecture, MVC, Layered, Microservices, and other patterns
- 🔍 Automatic API Discovery: Scans Go source code to detect HTTP endpoints across all packages
- 📦 Smart Struct Detection: Analyzes all project structs and generates accurate JSON bodies based on real type definitions
- 🎯 Cross-Package Resolution: Resolves types and relationships across different packages and modules
- 📝 Annotation Support: Uses special comments to enhance endpoint documentation
- 🏗️ Framework Support: Works with popular Go web frameworks (Gin, Chi, Echo, Fiber, Gorilla Mux, net/http)
- 🚀 GraphQL Support: Detects and documents GraphQL endpoints with query/mutation/subscription support
- 🔍 Smart Body Detection: Matches variables to actual struct definitions for precise JSON generation
- 📁 Smart Organization: Groups endpoints by folders with configurable depth
- 🏷️ Tag-based Grouping: Creates additional organization using
@tagannotations - 🌍 Environment Generation: Creates Postman environments with base URLs
- ⚡ Fast AST Analysis: Uses Go's AST parsing for reliable endpoint detection
- 🔄 REST & GraphQL: Full support for both REST and GraphQL API documentation
go install github.com/williamkoller/postman-gen/cmd/postman-gen@latestgit clone https://github.com/williamkoller/postman-gen.git
cd postman-gen
go build -o postman-gen cmd/postman-gen/main.gogo run cmd/postman-gen/main.go [flags]-
Write your handlers with JSON processing:
func CreatePayment(w http.ResponseWriter, r *http.Request) { var payment map[string]interface{} json.NewDecoder(r.Body).Decode(&payment) // ← Automatically detected! // your handler logic }
-
Generate Postman collection:
./postman-gen -dir . -name "My API" -out collection.json
-
Import
collection.jsoninto Postman - JSON bodies included automatically!
-
Add annotations to your Go handlers:
// @route POST /api/users Create user // @header Content-Type: application/json // @body {"name":"John Doe","email":"john@example.com","age":30} func CreateUser(c *gin.Context) { // your handler code }
-
Generate and import as above
# Generate collection from current directory
./postman-gen -dir . -out collection.json
# Generate collection with custom name and base URL
./postman-gen -dir . -name "My API" -base-url "http://localhost:3000" -out api-collection.json# Complete setup with environment and organization
./postman-gen \
-dir ./project \
-name "My REST API" \
-base-url "https://api.example.com" \
-group-depth 2 \
-group-by-method \
-tag-folders \
-out ./collections/api.postman_collection.json \
-env-out ./collections/dev.postman_environment.json \
-env-name "Development"# Test the tool with a single Go file containing @body annotations
echo 'package main
// @route POST /api/users Create user
// @header Content-Type: application/json
// @body {"name":"John Doe","email":"john@example.com","age":30}
func CreateUser() {}
func main() {}' > test.go
./postman-gen -dir test.go -name "Test API" -out test-collection.jsonpackage main
import "github.com/gin-gonic/gin"
// @route POST /api/v1/users Create user
// @header Content-Type: application/json
// @header Authorization: Bearer {{token}}
// @body {"name":"John Silva","email":"john@example.com","age":30,"active":true}
// @tag users
// @tag v1
func CreateUser(c *gin.Context) {
// Handler implementation
}
// @route PUT /api/v1/users/{id} Update user
// @header Authorization: Bearer {{token}}
// @body {"name":"John Silva Updated","email":"john.new@example.com"}
// @tag users
func UpdateUser(c *gin.Context) {
// Handler implementation
}Result in Postman collection:
- ✅ POST and PUT requests with JSON bodies included
- ✅ Authorization and content-type headers configured
- ✅ Organized by tags in folders
- ✅ Variables {{token}} and {{baseUrl}} ready to use
// This code will automatically generate appropriate JSON bodies
func CreateUser(w http.ResponseWriter, r *http.Request) {
var user map[string]interface{}
json.NewDecoder(r.Body).Decode(&user)
// Generates: {"name":"string","email":"string","id":"string"}
}
func UpdateProfile(w http.ResponseWriter, r *http.Request) {
var updateRequest map[string]interface{}
json.NewDecoder(r.Body).Decode(&updateRequest)
// Generates: {"id":"string","name":"string","value":"string"}
}
func ProcessData(c *gin.Context) {
var request map[string]interface{}
c.ShouldBindJSON(&request)
// Generates: {"data":"string","parameters":{}}
}Generated Postman Collection includes:
- ✅ Realistic JSON bodies for each endpoint
- ✅ Proper Content-Type headers
- ✅ Context-aware examples (payment, webhook, user data)
- ✅ No manual annotations required
| Flag | Type | Default | Description | Example |
|---|---|---|---|---|
-dir |
string | "." |
Root directory of the Go project to scan | -dir ./my-api |
-name |
string | "Go API" |
Name of the Postman collection | -name "User Service API" |
-base-url |
string | "http://localhost:8080" |
Base URL for the {{baseUrl}} variable | -base-url "https://api.myapp.com" |
-out |
string | "" |
Output file for the collection (empty = stdout) | -out api-collection.json |
| Flag | Type | Default | Description |
|---|---|---|---|
-group-depth |
int | 1 |
Folder grouping depth (0 = no grouping) |
-group-by-method |
bool | false |
Create HTTP method subfolders |
-tag-folders |
bool | false |
Create additional 'By Tag' folder tree |
| Flag | Type | Default | Description |
|---|---|---|---|
-env-out |
string | "" |
Output file for Postman environment (optional) |
-env-name |
string | "Local" |
Name of the Postman environment |
| Flag | Type | Default | Description |
|---|---|---|---|
-use-types |
bool | true |
Use enhanced type analysis (currently uses AST fallback) |
-build-tags |
string | "" |
Build tags for type analysis |
# Basic collection
./postman-gen -dir . -out api.json
# Production-ready setup
./postman-gen -dir ./src -name "Production API" -base-url "https://api.prod.com" \
-group-depth 2 -tag-folders -out prod-collection.json \
-env-out prod-environment.json -env-name "Production"
# Development with method grouping
./postman-gen -dir . -name "Dev API" -group-by-method -out dev-collection.jsonEnhance your API documentation using special comments in your Go code:
// @route GET /api/users/{id} Get user by ID
// @rest GET /api/users/{id} Get user by ID (alternative syntax)
func GetUser(c *gin.Context) {
// handler implementation
}// @header Authorization: Bearer {token}
// @header Content-Type: application/json
// @route POST /api/users Create new user
func CreateUser(c *gin.Context) {
// handler implementation
}Use the @body annotation to include JSON bodies in Postman collection requests:
Basic example:
// @body {"name": "John Doe", "email": "john@example.com"}
// @route POST /api/users Create user
func CreateUser(c *gin.Context) {
// handler implementation
}Example with complex data:
// @header Content-Type: application/json
// @header Authorization: Bearer {{token}}
// @body {"user_id":1,"items":[{"product_id":123,"quantity":2,"price":29.99}],"total":59.98}
// @route POST /api/orders Create order
// @tag orders
func CreateOrder(c *gin.Context) {
// handler implementation
}Example with multiple annotations:
// @header Authorization: Bearer {{token}}
// @header Content-Type: application/json
// @body {"name":"John Silva","email":"john@example.com","age":30,"active":true}
// @tag users
// @tag v1
// @route POST /api/v1/users Create user
func CreateUser(c *gin.Context) {
var user User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
// creation logic
}Example for updates (PUT/PATCH):
// @header Authorization: Bearer {{token}}
// @header Content-Type: application/json
// @body {"name":"John Silva Updated","email":"john.new@example.com"}
// @route PUT /api/v1/users/{id} Update user
// @tag users
func UpdateUser(c *gin.Context) {
// handler implementation
}💡 Tip: The JSON body defined in
@bodywill be automatically included in the Postman request withContent-Type: application/jsonand proper formatting.
NEW! postman-gen now features intelligent project analysis that comprehensively scans your entire Go project to understand its architecture and generate accurate JSON bodies based on real struct definitions - no annotations required!
// Define your structs anywhere in the project
type CreateUserRequest struct {
Name string `json:"name" validate:"required"`
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required,min=8"`
}
type Product struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Price float64 `json:"price"`
Category string `json:"category"`
InStock bool `json:"in_stock"`
}
// Use them in handlers - postman-gen will automatically match and generate accurate JSON
func CreateUser(w http.ResponseWriter, r *http.Request) {
var createUserReq CreateUserRequest // ← Automatically generates: {"name":"string","email":"string","password":"string"}
json.NewDecoder(r.Body).Decode(&createUserReq)
}
func CreateProduct(w http.ResponseWriter, r *http.Request) {
var product Product // ← Automatically generates: {"id":0,"name":"string","description":"string","price":0.0,"category":"string","in_stock":false}
json.NewDecoder(r.Body).Decode(&product)
}🧠 Intelligent Analysis Features:
- 🏗️ Architecture Detection: Automatically detects Clean Architecture, MVC, Layered, Microservices patterns
- 📦 Cross-Package Resolution: Finds struct definitions across all packages in your project
- 🎯 Smart Variable Matching: Matches handler variables to actual struct definitions
- 🔍 Type-Aware Generation: Generates JSON with correct Go types (int → 0, bool → false, []string → ["string"])
- 🏷️ JSON Tag Support: Respects
json:"fieldname"tags and validation rules
Supported Detection Patterns:
json.NewDecoder(r.Body).Decode(&variable)c.ShouldBindJSON(&variable)/c.BindJSON(&variable)json.Unmarshal(data, &variable)io.ReadAll(r.Body)followed by JSON processing
Smart Fallback System:
If specific structs aren't found, falls back to intelligent variable name analysis:
- Variables containing
user→ User JSON with name, email, id - Variables containing
create/post→ Creation JSON with name, value, type - Variables containing
update/put/patch→ Update JSON with id, name, value - Variables containing
request/req→ Generic request JSON with data and parameters
// @graphql query /graphql Get users query
// @query query GetUsers { users { id name email } }
// @variables {"limit": 10, "offset": 0}
func GraphQLHandler(c *gin.Context) {
// GraphQL handler implementation
}// @graphql mutation /graphql Create user mutation
// @query mutation CreateUser($input: UserInput!) { createUser(input: $input) { id name } }
// @variables {"input": {"name": "John", "email": "john@example.com"}}
func GraphQLMutationHandler(c *gin.Context) {
// GraphQL mutation handler
}// @graphql subscription /graphql User updates subscription
// @query subscription UserUpdates { userUpdated { id name status } }
func GraphQLSubscriptionHandler(c *gin.Context) {
// GraphQL subscription handler
}// @schema type User { id: ID! name: String! email: String! }
// @graphql query /graphql Get users
func GraphQLHandler(c *gin.Context) {
// handler implementation
}// @tag users
// @tag authentication
// @route GET /api/users List users
func ListUsers(c *gin.Context) {
// handler implementation
}The tool automatically detects endpoints from these popular Go web frameworks:
- Gin:
router.GET(),router.POST(), etc. - Chi:
r.Get(),r.Post(),r.Route(),r.Group() - Echo:
e.GET(),e.POST(),e.Group() - Fiber:
app.Get(),app.Post(),app.Group() - Gorilla Mux:
router.HandleFunc(),router.Handle(),router.PathPrefix() - net/http:
http.HandleFunc(),mux.Handle()
- gqlgen: Automatic detection of
/graphqlendpoints - graphql-go: Detection of GraphQL handlers
- 99designs/gqlgen: Schema-first GraphQL support
- Custom GraphQL: Any endpoint with "graphql" or "graph" in the path
- Manual Annotation: Use
@graphqlannotations for complete control
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
// @route GET /ping Simple health check
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "pong"})
})
// @tag users
// @header Authorization: Bearer {token}
// @route GET /users/{id} Get user by ID
r.GET("/users/:id", getUserHandler)
r.Run()
}package main
import (
"github.com/gin-gonic/gin"
"github.com/99designs/gqlgen/graphql/handler"
)
func main() {
r := gin.Default()
// @graphql query /graphql Get users and posts
// @query query GetData { users { id name } posts { title } }
// @header Authorization: Bearer {token}
// @tag graphql
r.POST("/graphql", gin.WrapH(handler.NewDefaultServer(generated.NewExecutableSchema())))
// @graphql mutation /graphql Create user mutation
// @query mutation CreateUser($input: UserInput!) { createUser(input: $input) { id name } }
// @variables {"input": {"name": "John", "email": "john@example.com"}}
// @tag users
r.POST("/graphql", graphqlHandler)
r.Run()
}package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
// REST endpoints
// @rest GET /api/health Check API health
r.GET("/api/health", healthHandler)
// @rest POST /api/users Create user via REST
// @body {"name": "John", "email": "john@example.com"}
r.POST("/api/users", createUserHandler)
// GraphQL endpoint
// @graphql query /graphql GraphQL endpoint for complex queries
// @query query { users { id name email } }
r.POST("/graphql", graphqlHandler)
r.Run()
}My API Collection/
├── ping/
│ └── GET /ping
└── users/
└── GET /users/{id}
└── By Tag/
└── users/
└── GET /users/{id}
postman-gen/
├── cmd/
│ └── postman-gen/
│ └── main.go # Main application entry point
├── internal/
│ ├── postman/
│ │ ├── postman.go # Postman collection builder
│ │ └── env.go # Environment file generator
│ └── scan/
│ ├── scan.go # AST-based endpoint scanner
│ └── typescan.go # Type-aware analysis (fallback to AST)
├── go.mod
├── go.sum
└── README.md
The tool uses an intelligent multi-phase approach:
- 🧠 Project Analysis: Comprehensively scans the entire Go project to understand architecture patterns, struct definitions, and type relationships
- 🏗️ Architecture Detection: Automatically detects Clean Architecture, MVC, Layered, Microservices patterns with confidence scoring
- 📦 Cross-Package Resolution: Maps all structs, interfaces, and types across packages for intelligent type matching
- 🔍 AST Scanning: Parses Go source files to detect HTTP route registrations and handler functions
- 🎯 Smart Body Generation: Matches handler variables to actual project struct definitions for accurate JSON generation
- 📝 Annotation Processing: Extracts additional documentation from special comments (optional enhancement)
- 🔧 Collection Building: Organizes endpoints into Postman collection format with precisely generated request bodies
1. Define clear struct types (Recommended):
// ✅ Best - will generate accurate JSON based on struct definition
type CreateUserRequest struct {
Name string `json:"name"`
Email string `json:"email"`
Password string `json:"password"`
}
func CreateUser(w http.ResponseWriter, r *http.Request) {
var createUserReq CreateUserRequest // ← Perfect match!
json.NewDecoder(r.Body).Decode(&createUserReq)
}2. Use descriptive variable names as fallback:
// ✅ Good - will generate context-aware JSON if struct not found
var userRequest map[string]interface{}
json.NewDecoder(r.Body).Decode(&userRequest)
// ❌ Less optimal - will generate generic JSON
var data map[string]interface{}
json.NewDecoder(r.Body).Decode(&data)3. Supported frameworks and patterns:
// ✅ Standard library
json.NewDecoder(r.Body).Decode(&variable)
// ✅ Gin framework
c.ShouldBindJSON(&variable)
c.BindJSON(&variable)
// ✅ Direct unmarshaling
json.Unmarshal(bodyBytes, &variable)
// ✅ Read-then-unmarshal pattern
body, _ := io.ReadAll(r.Body)
json.Unmarshal(body, &variable)4. Architecture Compatibility:
postman-gen automatically adapts to various Go project architectures:
// 🏗️ Clean Architecture
domain/
entities/user.go // ← User struct detected
usecase/
user_usecase.go // ← Business logic
delivery/http/
user_handler.go // ← Handler using User struct
// 🌐 MVC Pattern
models/user.go // ← Model detected
controllers/
user_controller.go // ← Controller using model
// ⚡ Microservice
internal/
domain/user.go // ← Domain entity
handlers/user.go // ← HTTP handlers5. Context-aware naming for better examples:
paymentRequest,payment→ Payment JSONuserRequest,user→ User profile JSONwebhookData,webhook→ Webhook event JSONorderData,order→ Order with items JSONcancelRequest→ Cancellation reason JSON
1. Keep JSONs valid:
// ✅ Correct
// @body {"name":"John","age":30,"active":true}
// ❌ Incorrect (invalid JSON)
// @body {name:"John",age:30,active:true}2. Use realistic data:
// ✅ Good example with realistic data
// @body {"email":"user@example.com","password":"password123","remember_me":true}
// ❌ Too generic example
// @body {"field1":"value1","field2":"value2"}3. Combine with appropriate headers:
// ✅ Consistent headers
// @header Content-Type: application/json
// @header Authorization: Bearer {{token}}
// @body {"data":"example"}4. Organize by complexity:
// For simple endpoints
// @body {"name":"John","email":"john@example.com"}
// For complex endpoints with arrays and nested objects
// @body {"user":{"name":"John","profile":{"age":30}},"preferences":["email","sms"]}5. Use Postman variables:
// ✅ Use variables for dynamic data
// @body {"user_id":"{{user_id}}","timestamp":"{{$timestamp}}"}-
Write your handlers with descriptive variable names:
func CreatePayment(w http.ResponseWriter, r *http.Request) { var payment map[string]interface{} // ← Descriptive name json.NewDecoder(r.Body).Decode(&payment) // handler logic }
-
Generate the collection:
./postman-gen -dir . -name "My API v1" -base-url "http://localhost:8080" -out api-collection.json
-
Import into Postman and test:
- JSON bodies automatically included based on code analysis
- Context-aware examples (payment, user, webhook, etc.)
- Headers automatically configured
-
Add annotations for custom control:
// @route POST /api/users Create user // @header Authorization: Bearer {{token}} // @body {"name":"John","email":"john@example.com"} func CreateUser() {}
-
Generate and import as above
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Issue: internal error: package "errors" without types
Solution: The tool automatically falls back to AST scanning mode to avoid this issue.
Issue: No endpoints detected
Solution: Make sure your code uses supported frameworks or add @route annotations.
Issue: Missing endpoints Solution: Check that your route registrations are in the scanned directory and use supported patterns.
- ✅ GraphQL Support: Full support for GraphQL queries, mutations, and subscriptions
- ✅ REST API Enhancement: Improved REST endpoint detection and documentation
- ✅ Multi-protocol Support: Support for both REST and GraphQL in the same API
- 🔄 gRPC Support: Detection and documentation of gRPC services
- 📊 OpenAPI/Swagger Integration: Generate OpenAPI specs alongside Postman collections
- 🎨 Custom Annotation Types: User-defined annotation types for specialized documentation
- 🧪 Request/Response Examples: Auto-generate example requests and responses
- ✅ CI/CD Integration: GitHub Actions workflows for automated testing, building, and releases
- 📝 TypeScript Support: Generate TypeScript definitions from API documentation
- 🔍 WebSocket Support: Documentation for WebSocket endpoints
If you encounter any issues or have questions, please open an issue on GitHub.