api-svc is a collection of reusable domain services for Go HTTP APIs:
billing, credits/tokens, identity, payments, and contact. Each service is
packaged as plain Go with clear ports (interfaces) for persistence and
third‑party providers. Some services include optional HTTP handlers
(chi-based via api-toolkit) and Postgres adapters + embedded migrations.
This repository is intentionally both human- and agent-friendly: predictable folder layout, small packages, explicit wiring, and minimal hidden magic.
- Domain logic in
Servicetypes; adapters stay thin. - Depend on stable interfaces at boundaries (
github.com/aatuh/api-toolkit/ports). - Make persistence/provider swaps straightforward.
- Keep wiring explicit and test-friendly (fakes over ports).
billingsvc— billing profiles, invoices, “outstanding” invoicing, and webhook processing.- HTTP:
billingsvc/http - Postgres:
billingsvc/postgres - Migrations:
billingsvc/migrations(embeddedembed.FS)
- HTTP:
creditsvc— token/credit accounts + transaction ledger.- Postgres:
creditsvc/postgres - Migrations:
creditsvc/migrations(embeddedembed.FS)
- Postgres:
identity— external identity → local user, role management.- HTTP:
identity/http(ensure middleware + profile endpoints) - Postgres:
identity/postgres(configurable table names) - Migrations:
identity.MustMigrationsFS()(embeddedfs.FS)
- HTTP:
paymentsvc— token pack catalog + checkout + webhook handling.- HTTP:
paymentsvc/http(Stripe webhook handler)
- HTTP:
contact— contact form message delivery via an emailSender.- HTTP:
contact/http(endpoint wrapper; you provide decode/validation)
- HTTP:
go get github.com/aatuh/api-svc@latestThis repo is a library, not a runnable server. Your application wires services with adapters (for Postgres, Stripe, email, etc.) and mounts the HTTP handlers onto your router.
package main
import (
"log"
"net/http"
"github.com/aatuh/api-svc/identity"
identityhttp "github.com/aatuh/api-svc/identity/http"
identitypg "github.com/aatuh/api-svc/identity/postgres"
"github.com/aatuh/api-toolkit/adapters/chi"
"github.com/aatuh/api-toolkit/adapters/clock"
"github.com/aatuh/api-toolkit/adapters/logzap"
"github.com/aatuh/api-toolkit/adapters/pgxpool"
"github.com/aatuh/api-toolkit/adapters/txpostgres"
"github.com/aatuh/api-toolkit/adapters/uuid"
)
func main() {
pool, err := pgxpool.New("postgres://user:pass@localhost:5432/app?sslmode=disable")
if err != nil {
log.Fatal(err)
}
defer pool.Close()
tx := txpostgres.New(pool)
logr := logzap.NewProduction()
clk := clock.NewSystemClock()
ids := uuid.NewUUIDGen()
repo := identitypg.NewRepo(pool, identitypg.DefaultConfig())
svc := identity.NewDefault(repo, tx, logr, clk, ids)
r := chi.New()
r.Mount("/me", identityhttp.NewProfileHandler(identityhttp.ProfileConfig{
Service: svc,
}).Routes())
log.Fatal(http.ListenAndServe(":8080", r))
}Configuration is expressed as plain structs. Some services include helper
loaders that read environment variables via api-toolkit/config.Loader.
Some services include Postgres adapters and embedded SQL migrations.
Migrations are designed to be run via api-toolkit/migrator (or its
adapters/migrate wrapper) without requiring a migrations directory on
disk.
package main
import (
"context"
"io/fs"
billingmigrations "github.com/aatuh/api-svc/billingsvc/migrations"
creditsmigrations "github.com/aatuh/api-svc/creditsvc/migrations"
"github.com/aatuh/api-svc/identity"
"github.com/aatuh/api-toolkit/adapters/migrate"
"github.com/aatuh/api-toolkit/adapters/logzap"
)
func migrateDB(ctx context.Context, dsn string) error {
log := logzap.NewProduction()
m, err := migrate.New(migrate.Options{
DSN: dsn,
Log: log,
EmbeddedFSs: []fs.FS{
identity.MustMigrationsFS(),
billingmigrations.Migrations,
creditsmigrations.Migrations,
},
})
if err != nil {
return err
}
defer m.Close()
return m.Up(ctx, "")
}Services that ship HTTP handlers expose reusable routers/handlers that
follow a consistent flow: decode → validate → service call → encode.
Defaults use RFC‑7807 Problem+JSON via api-toolkit/httpx, and most
handlers allow overriding the encoding/problem writers.
Starting points:
- Billing routes:
billingsvc/http/handler.go - Contact endpoint wrapper:
contact/http/handler.go - Identity middleware and profile endpoints:
identity/http/middleware.go,identity/http/profile_handler.go - Stripe webhook fan-out:
paymentsvc/http/stripe_webhook.go
- Run:
go test ./...(if you’re inside a larger repo with a parentgo.workthat doesn’t include this module, useGOWORK=off go test ./...) - Format:
gofmt -w .
Apache-2.0. See LICENSE.