Create an API Service
Create an API Service
Section titled “Create an API Service”This guide builds a simple user service with login and profile endpoints. You will write a .api DSL file, generate the project, and fill in the business logic.
Step 1 — Write the API DSL
Section titled “Step 1 — Write the API DSL”Create a directory and write the DSL:
mkdir user-api && cd user-apiCreate user.api:
syntax = "v1"
type ( LoginReq { Username string `json:"username"` Password string `json:"password"` }
LoginResp { Token string `json:"token"` }
UserInfoReq { Id int64 `path:"id"` }
UserInfoResp { Id int64 `json:"id"` Username string `json:"username"` Email string `json:"email"` })
service user-api { @handler Login post /user/login (LoginReq) returns (LoginResp)
@handler GetUserInfo get /user/:id (UserInfoReq) returns (UserInfoResp)}Step 2 — Generate the Service
Section titled “Step 2 — Generate the Service”goctl api go -api user.api -dir .go mod init user-apigo mod tidyThe generated layout:
user-api/├── etc/│ └── user-api.yaml├── internal/│ ├── config/config.go│ ├── handler/│ │ ├── loginhandler.go # auto-generated, do not edit│ │ ├── getuserinfohandler.go # auto-generated, do not edit│ │ └── routes.go│ ├── logic/│ │ ├── loginlogic.go # ← implement this│ │ └── getuserinfologic.go # ← implement this│ ├── svc/servicecontext.go│ └── types/types.go # auto-generated from DSL└── main.goStep 3 — Implement Logic
Section titled “Step 3 — Implement Logic”Edit internal/logic/loginlogic.go:
func (l *LoginLogic) Login(req *types.LoginReq) (resp *types.LoginResp, err error) { // In production: verify credentials against DB, issue a real JWT if req.Username == "admin" && req.Password == "secret" { return &types.LoginResp{ Token: "mock-jwt-token-for-" + req.Username, }, nil } return nil, errors.New("invalid credentials")}Edit internal/logic/getuserinfologic.go:
func (l *GetUserInfoLogic) GetUserInfo(req *types.UserInfoReq) (resp *types.UserInfoResp, err error) { // In production: query from DB using l.svcCtx.DB return &types.UserInfoResp{ Id: req.Id, Username: "alice", Email: "alice@example.com", }, nil}Step 4 — Run and Test
Section titled “Step 4 — Run and Test”go run main.goIn another terminal:
# Logincurl -s -X POST http://localhost:8888/user/login \ -H 'Content-Type: application/json' \ -d '{"username":"admin","password":"secret"}'# {"token":"mock-jwt-token-for-admin"}
# Get user infocurl http://localhost:8888/user/1# {"id":1,"username":"alice","email":"alice@example.com"}Regenerating After DSL Changes
Section titled “Regenerating After DSL Changes”Whenever you change user.api, regenerate without overwriting your logic files:
goctl api go -api user.api -dir .goctl only overwrites files it owns (handler/, types/, routes.go). Your logic/ files are preserved.
Next Steps
Section titled “Next Steps”- Add JWT middleware to protect endpoints
- Connect a database model
- Create an RPC service →