Sirloin API
The contract surface of sirloin. For service overview see Sirloin. For generated proto reference see proto-api.
Surface Map
Sirloin exposes four gRPC services and a small set of HTTP endpoints (health, webhooks, MCP). The single Go process listens on three ports:
| Port | Purpose | Source |
|---|---|---|
50051 | gRPC + gRPC-Web (h2c) | apps/sirloin/cmd/app/main.go (grpcHTTPServer) |
8087 | Webhook intake (HTTP) | apps/sirloin/cmd/app/main.go (webhookHTTPServer) |
8086 | MCP / Foxy360 (HTTP) | apps/sirloin/cmd/app/main.go (mcpHTTPServer) |
Defaults: container ports per docker-compose.yml (sirloin service).
Default SIRLOIN_PORT=:50051 per apps/sirloin/internal/app/config/config.go.
gRPC Services
Proto contracts live under proto/sirloin/v5/. Generated stubs are checked
into apps/sirloin/internal/pkg/pb/. RPC list below is summarised; for full
request/response shapes refer to the proto files and the generated docs at
proto-api.
SirloinService (proto/sirloin/v5/sirloin.proto)
End-user surface: characters, media, profile, KYC. Consumed by brisket over gRPC-Web. Selected RPCs (28 total):
CreateCharacter,UpdateCharacter,ListCharacters,DeleteCharacterGetCharacterReferenceImageUploadURL,GetCharacterReferenceDatasetUploadURLsVerifyCharacterReferenceDatasetImage,DeleteCharacterReferenceDatasetImageUpdateCharacterReferenceDataset,TriggerCharacterReferenceImageUploadedGenerateMedia,ListMedia,ToggleMediaFavorite,ToggleMediaArchived,SetMediaDownloaded,ListMediaTags,ListMediaExamplesGetUserProfile,UpdateUserProfile,RequestWelcomePics,SubmitFeedbackGetInstagramProfile,StartKYCVerification
BillingService (proto/sirloin/v5/billing.proto)
Billing surface: subscriptions, payments, products, coupons. Consumed by brisket and strip. Selected RPCs:
GetCurrentUsage,ListProducts,GetWorkflowPricingCreatePrimerCheckout,SubmitPaidInvoice,GetPayment,GetTransactionsGetSubscriptionDetails,CancelSubscription,ReactivateSubscription,CancelScheduledDowngrade,ProvideCancellationBenefitRetryDunningPayment,ValidateCoupon,SetReferralCodeGetPaymentMethods,AddPaymentMethod,DeletePaymentMethod,SetPrimaryPaymentMethod,CreateVaultingSessionUpdateBillingAddress,UpdateNextBillingDateForTesting(test-only)
Behaviour notes (deferred activation, polling, invariants) are described
in apps/sirloin/internal/app/services/billing/BILLING.md and the
billing runbook.
StripService (proto/sirloin/v5/strip.proto)
Admin surface consumed exclusively by strip (SSR admin). Auth via short-lived admin Clerk token (see auth-model). Selected RPCs:
StripListUsers,StripUpdateUserStripListCharacters,StripCreateCharacter,StripUpdateCharacter,StripDeleteCharacter,StripBypassCharacterOnboardingChecksStripListMedia,StripFailMedia,StripListDatasetImagesStripListPopularExamples,StripListPopularCategoriesStripLogAudit,StripListAuditLogs,StripGetAuditLog
FlankStorageService — removed
Under T-Bone the workflow engine and storage moved into brain, which owns workflows, subworkflows, adapters, secrets, and executions over an HTTP API. The sirloin-hosted
FlankStorageService(workflow/adapter/secret/execution CRUD inproto/sirloin/v5/flank.proto), theFlankMCProute, and the flank DB tables have been deleted. Flank is now only the visual workflow editor and reads/writes brain directly.The workflow-facing RPCs that survive are brain-backed and live on the main protos:
ListGenerationCatalog(proto/sirloin/v5/sirloin.proto) andGetWorkflowPricing(proto/sirloin/v5/billing.proto).
gRPC Health
grpc.health.v1.Health implemented in
apps/sirloin/internal/app/services/health.go. Used by the container
healthcheck (/bin/grpc_health_probe -addr=:50051).
REST Endpoints
Sirloin’s HTTP surface is intentionally narrow. Routes registered in
apps/sirloin/cmd/app/main.go against webhookMux, grpcHTTPMux, and
mcpMux.
| Method | Path | Server | Auth | Source |
|---|---|---|---|---|
| GET | /health | gRPC HTTP (50051) | none | internal/app/services/health.go |
| POST | /webhooks/chargebee/events | webhooks (8087) | HTTP Basic (SIRLOIN_CHARGEBEE_WEBHOOK_USERNAME / _PASSWORD) | internal/app/services/billing/webhooks/chargebeewebhook.go |
| POST | /webhooks/primer/disputes | webhooks (8087) | HMAC over SIRLOIN_PRIMER_WEBHOOK_SECRET | internal/app/services/billing/disputes/primerwebhook.go |
| POST | /webhooks/primer/payments | webhooks (8087) | HMAC over SIRLOIN_PRIMER_WEBHOOK_SECRET | internal/app/services/billing/webhooks/ (NewPrimerPaymentsWebhookHandler) |
| POST | /webhooks/ondato/verification-status | webhooks (8087) | shared secret SIRLOIN_ONDATO_WEBHOOK_SECRET | internal/app/services/characters/ondato_webhook.go |
| ANY | ${SIRLOIN_FOXY360_BASE_PATH}/* | MCP (8086) | Clerk (SIRLOIN_FOXY360_CLERK_API_KEY) via OAuth proxy | internal/app/foxy360/, internal/app/mcpoauth/ |
grpcHTTPMux falls back to a 404 for everything except /health and the
gRPC + gRPC-Web protocol routes (apps/sirloin/cmd/app/main.go).
Webhooks Received
Chargebee Events
- Path:
POST /webhooks/chargebee/eventson port8087 - Auth: HTTP Basic with
SIRLOIN_CHARGEBEE_WEBHOOK_USERNAME/SIRLOIN_CHARGEBEE_WEBHOOK_PASSWORD. Missing creds → all webhooks rejected (config.gowarns at startup). - Payload: Chargebee event JSON (
event_type,content). - Behaviour: webhook is a fallback; sirloin’s own poller (every 15s, see
internal/app/services/billing/events/poller.go) is the authoritative ingest path.
Primer Disputes
- Path:
POST /webhooks/primer/disputeson port8087 - Auth: HMAC verified with
SIRLOIN_PRIMER_WEBHOOK_SECRET. 3-minute clock skew window (primer.WebhookSignedAtWithinSkew). - Body limit: 1 MiB (
maxPrimerWebhookBodyBytes).
Primer Payments
- Path:
POST /webhooks/primer/paymentson port8087 - Auth: same HMAC scheme as disputes.
- Behaviour: feeds the unified payment processor
(
internal/app/services/billing/payments/processor.go).
Ondato KYC
- Path:
POST /webhooks/ondato/verification-statuson port8087 - Auth: shared secret
SIRLOIN_ONDATO_WEBHOOK_SECRET.
Examples
# health probecurl -fsS http://localhost:50051/health
# gRPC reflection (dev only — sirloin docker-compose ships grpcui on :8820 too)grpcurl -plaintext localhost:50051 listgrpcurl -plaintext localhost:50051 sirloin.v5.BillingService/ListProductsVersioning
Proto package is pinned at sirloin.v5. Backwards-incompatible changes
require a new package version; field deprecation follows
documentation standard and
auth-model for auth changes. TODO(@zen): no
formal deprecation policy doc exists yet — confirm or add ADR.
TODO(@zen)
- TODO(@zen): is there a documented
sirloin.v5deprecation policy beyond proto file conventions? - Foxy360 MCP routes are internal-only. The
${SIRLOIN_FOXY360_BASE_PATH}/*surface is gated by Clerk verification (SIRLOIN_FOXY360_CLERK_API_KEY) through an OAuth proxy and exposes admin/analytics tooling. Source:apps/sirloin/internal/app/foxy360/server.go:1and registration inapps/sirloin/cmd/app/main.go(mcpHTTPServer). - Primer payments webhook uses the same 1 MiB body cap as disputes.
maxPrimerPaymentBodyBytes = 1 * 1024 * 1024inapps/sirloin/internal/app/services/billing/webhooks/primerpaymentwebhook.go:22, matchingmaxPrimerWebhookBodyBytesinapps/sirloin/internal/app/services/billing/disputes/primerwebhook.go:26.