56 results available
Sign in
Skills directory

go-api

encoredev

·

Last changed
Hardened

This skill has been hardened by Chainguard

Last changed

This version passed the hardening gate. Hardening applied 9 targeted changes and preserved all other text. Classified findings before hardening: 0. Classified findings closed: 0. Classified findings remaining: 0. Unclassified scanner findings remaining: 0. Review findings closed: 7. Review findings remaining: 3.


Open before hardening

None

Open after hardening

None


Expand
File
Group
Subtype
Severity
Status

No findings available

0 findings


SKILL.md

Encore Go API Endpoints

Instructions

When creating API endpoints with Encore Go, follow these patterns:

1. Basic API Endpoint

Use the //encore:api annotation above your function:

package user

import "context"

type GetUserParams struct {
    ID string
}

type User struct {
    ID    string `json:"id"`
    Email string `json:"email"`
    Name  string `json:"name"`
}

//encore:api auth method=GET path=/users/:id
func GetUser(ctx context.Context, params *GetUserParams) (*User, error) {
    // Implementation
    return &User{ID: params.ID, Email: "user@example.com", Name: "John"}, nil
}

2. POST with Request Body

type CreateUserParams struct {
    Email string `json:"email"`
    Name  string `json:"name"`
}

//encore:api public method=POST path=/users
func CreateUser(ctx context.Context, params *CreateUserParams) (*User, error) {
    // Implementation
    return &User{ID: "new-id", Email: params.Email, Name: params.Name}, nil
}

API Annotation Options

OptionValuesDescription

public

-

Accessible from outside

private

-

Only callable from other services

auth

-

Requires authentication

method

GET, POST, PUT, PATCH, DELETE

HTTP method

path

string

URL path with :param for path params

sensitive

-

Redacts request/response payloads from traces

Endpoints marked auth only work when the app defines an auth handler. Set one up before relying on auth endpoints.

Examples

//encore:api public method=GET path=/health
//encore:api private method=POST path=/internal/process
//encore:api auth method=GET path=/profile
//encore:api public sensitive method=POST path=/auth/login

Sensitive Data

Mark sensitive fields to redact them from tracing logs:

type LoginParams struct {
    Email    string `json:"email"`
    Password string `json:"password" encore:"sensitive"`
}

Tag session cookies, tokens, signatures, secrets and personal data the same way so they stay out of traces.

Or mark the entire endpoint as sensitive in the annotation:

//encore:api public sensitive method=POST path=/auth/login
func Login(ctx context.Context, params *LoginParams) (*TokenResponse, error) {
    // Request and response will be redacted from traces
}

Custom HTTP Status Codes

Return custom HTTP status codes using the encore:"httpstatus" tag:

type CreateResponse struct {
    ID     string `json:"id"`
    Status int    `encore:"httpstatus"`
}

//encore:api public method=POST path=/items
func CreateItem(ctx context.Context, params *CreateParams) (*CreateResponse, error) {
    item := createItem(params)
    return &CreateResponse{
        ID:     item.ID,
        Status: 201,  // Returns HTTP 201 Created
    }, nil
}

Request Parameter Sources

Path Parameters

// Path: /users/:id
type GetUserParams struct {
    ID string
}

In Encore Go, path parameters are passed as function arguments after ctx, in path order, before the optional request struct pointer.

Query Parameters

// Path: /users
type ListUsersParams struct {
    Limit  int `query:"limit"`
    Offset int `query:"offset"`
}

//encore:api public method=GET path=/users
func ListUsers(ctx context.Context, params *ListUsersParams) (*ListResponse, error) {
    // params.Limit and params.Offset come from query string
}

Headers

type WebhookParams struct {
    Signature string `header:"X-Webhook-Signature"`
    Payload   string `json:"payload"`
}

Binding a signature header does not verify it. A signature over the raw body cannot be checked from a typed struct, so verify webhook signatures in raw endpoints with a constant-time comparison, as described in encore-go-webhook.

Cookies

import "net/http"

type AuthParams struct {
    SessionCookie *http.Cookie `cookie:"session"`
    CSRFToken     string       `header:"X-CSRF-Token"`
}

//encore:api auth method=POST path=/logout
func Logout(ctx context.Context, params *AuthParams) error {
    // Access params.SessionCookie.Value
    return nil
}

Endpoints that use cookie authentication and change state must compare the CSRF token with the token bound to the session, and return errs.PermissionDenied when they differ.

Response Types

Standard Response

type Response struct {
    Message string `json:"message"`
}

//encore:api public method=GET path=/hello
func Hello(ctx context.Context) (*Response, error) {
    return &Response{Message: "Hello, World!"}, nil
}

No Response Body

//encore:api auth method=DELETE path=/users/:id
func DeleteUser(ctx context.Context, params *DeleteParams) error {
    // Return only error (no response body on success)
    return nil
}

No Request Parameters

//encore:api public method=GET path=/health
func Health(ctx context.Context) (*HealthResponse, error) {
    return &HealthResponse{Status: "ok"}, nil
}

Error Handling

Use errs package for proper HTTP error responses:

import "encore.dev/beta/errs"

//encore:api auth method=GET path=/users/:id
func GetUser(ctx context.Context, params *GetUserParams) (*User, error) {
    user, err := findUser(params.ID)
    if err != nil {
        return nil, err
    }
    if user == nil {
        return nil, &errs.Error{
            Code:    errs.NotFound,
            Message: "user not found",
        }
    }
    return user, nil
}

Common Error Codes

CodeHTTP StatusUsage

errs.NotFound

404

Resource doesn't exist

errs.InvalidArgument

400

Bad input

errs.Unauthenticated

401

Missing/invalid auth

errs.PermissionDenied

403

Not allowed

errs.AlreadyExists

409

Duplicate resource

Guidelines

  • Use //encore:api annotation above the function
  • Request params must be a pointer to a struct or omitted
  • Response must be a pointer to a struct (or omit for no body)
  • Always return error as the last return value
  • Use struct tags for JSON field names, query params, and headers
  • Path parameters are passed as function arguments, in path order, before the optional request struct pointer
  • Use public only for endpoints meant to be open, such as health checks or login; use auth for endpoints that read or change user data or return personal data, or private for internal use
  • Authentication is not authorization: check that the caller owns or may access a resource loaded by id, and return errs.PermissionDenied when that check fails
  • Validate request fields before use: reject empty or malformed values with errs.InvalidArgument, cap the limit query value at a sensible maximum, and reject a negative offset

Install

Install with chainctl
chainctl skill install public/encoredev/go-api:latest
Get started with chainctl
View source

Harden your own skills

Bring Chainguard's hardening pipeline to your first-party skills — custom rulesets, automated remediation, full audit trail.

Provenance

Upstream sourcehttps://github.com/encoredev/skills
Upstream commitcb69bb1f246274419aed69c84ee5815955c4c499
OCI reference

skills.cgr.dev/public/github.com/encoredev/encore/go-api:latest

License

Apache-2.0

Files

HARDENING.md

LICENSE

SKILL.md


The trusted source for open source

Talk to an expert
PrivacyTerms

Product

Chainguard ContainersChainguard LibrariesChainguard VMsChainguard OS PackagesChainguard ActionsChainguard Agent SkillsIntegrationsPricing
© 2026 Chainguard, Inc. All Rights Reserved.
Chainguard® and the Chainguard logo are registered trademarks of Chainguard, Inc. in the United States and/or other countries.
The other respective trademarks mentioned on this page are owned by the respective companies and use of them does not imply any affiliation or endorsement.