api

module
v1.1.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 24, 2026 License: Apache-2.0

README

Programmable operations for people who make things.

An open source manufacturing platform built to make factories
programmable, reliable, and increasingly autonomous.

Website  ·  Documentation  ·  API reference  ·  All repos


Why this exists

This project grew out of running a real manufacturing operation. It started as a way to locate material inside a circular knitting factory, and turned into the software that ran the orders, the inventory, the workflows, and eventually the operations around them.

Our philosophy is that ERPs should be programmable infrastructure. Our goal with OpenMRP is to provide a durable and performant foundation by which manufacturing operations can efficiently operate and automate their back office and factory operations. With this in mind, we have designed OpenMRP to scale with your company and deploy to any cloud provider or locally. Endpoints are idempotent, work is durable via transactional inboxes and outboxes, and systems are designed to be resilient to failure.

What it does

Items Materials, parts, products, product lines, categories, units of measure and unit groups
Engineering Bills of materials, production flows, production steps, consumptions and productions, rolled-up costing
Planning Demand forecasting, demand overrides, production schedules, publishing and releasing, work lists, operating calendars
Production Production runs, batches, batch operations, machines, departments, machine status and downtime tracking
Inventory Storage locations, lots, reconciliation, change logs, receipts, distribution-center locations
Purchasing Suppliers, purchase orders, deliveries and receiving
Shop floor Scanning stations, labels, picking, packing, shipping, carriers and service levels
Sales Customers, contacts, customer groups, territories, sales reps and targets, sales orders, order discounts
Pricing Account prices, volume discounts, discount codes, payment terms, shipping terms, exemptions
Customer portal A branded, custom-domain storefront where your customers register, order, check inventory, pay, and message you
Money Invoicing, accounts receivable and aging, collections, settlements, open credits, Stripe-backed transactions
Analytics Order, delivery, manufacturing and material analytics; pricing analysis; weeks of sales; quarterly orders; products on order
Communication Shared inbox, threaded messaging, email domains and inboxes, notifications and preferences, retention and compliance controls
Agents Agent configs, runs, memories, endpoint-tools with approval gates, agents in chat, reply drafts a human approves
Platform API keys, sandboxes, roles and permissions, audit events, request logs, email logs, idempotency, HubSpot and EDI integrations

Browse the API reference, or read the OpenAPI specification.

Production flows. A product's bill of materials and its routing are the same graph: materials feed production steps, steps yield parts, and every edge carries the quantity consumed or produced. Costs roll up along it.

A production flow running from raw yarn through knitting, dyeing, boarding, and packing to a finished SKU

Production schedules. A solver turns forecast demand into a week-by-week plan per SKU — run hours, utilisation, and what freezes when. It stays a draft until you publish it.

A draft production schedule laid out by SKU across thirteen weeks

Agents. @mention an agent in any thread and it works the same API you do. Tools that write are gated: the run stops, a human approves by name, and only then does it continue.

An agent run holding a customer update at an approval gate until a human approves it

Request logs. Every call the dashboard makes is a call you can make. Method, path, status, latency, and caller — whether that caller was a person, an API key, or an agent.

Request logs listing API calls with method, path, status, latency, and caller

Architecture

This repository is the backend: an HTTP gateway in front of six domain services that talk to each other over gRPC and to themselves over RabbitMQ.

flowchart LR
    subgraph clients [Clients]
        DASH[Dashboard]
        PORTAL[Customer portal]
        SDK["TypeScript / Go SDKs"]
        MCP[MCP server]
    end

    GW[["api-gateway<br/>auth · versioning<br/>idempotency · rate limits<br/>internal listener :8091"]]

    subgraph services [Domain services · gRPC]
        CORE[core-service]
        AUTH[auth-service]
        NOTIF[notification-service]
        BILL[billing-service]
        PLAT[platform-service]
        AGENT[agent-service]
    end

    MQ{{"RabbitMQ<br/>outbox / inbox"}}

    DASH & PORTAL & SDK & MCP --> GW
    GW --> CORE & AUTH & NOTIF & BILL & PLAT & AGENT
    AGENT -- "agent tool calls" --> GW
    CORE & AUTH & NOTIF & BILL & PLAT & AGENT <--> MQ

Agents run inside agent-service, and when a run calls a tool it loops back through the gateway rather than reaching into another service directly, so an agent's writes get the same auth, versioning, idempotency, and audit trail as anyone else's. That loop lands on a second gateway listener on port 8091, a ClusterIP that is never routed publicly and is gated by a shared token.

Messages cross between services through the outbox and inbox tables, so a publish commits in the same transaction as the state change it describes. At the moment, several services share a MySQL database; this will change after we finish migrating a legacy API to this repository.

Service Owns Store
core-service Items, production, inventory, orders MySQL
auth-service Identity, JWTs, API keys MySQL
notification-service Email, messaging, notifications MySQL
billing-service Subscriptions, payments MySQL
platform-service Audit events, request logs, idempotency MySQL
agent-service Agent runs, tools, memories PostgreSQL

Every service is layered the same way:

Layer Responsibility
Transport Thin, stateless HTTP / gRPC / RabbitMQ handlers. No business logic.
Service Business logic and transaction boundaries.
Mediator Reusable business steps, shared across services.
Repository Data persistence. SQL lives here, compiled by sqlc.
Domain Models, interfaces, and generated mocks.
services/[name]/
├── cmd/                        # Entry point (main.go, run.go, config.go)
├── internal/
│   ├── service/                # Business logic
│   ├── domain/                 # Models, interfaces, mocks
│   ├── mediator/               # Reusable business steps
│   └── infrastructure/
│       ├── repository/         # Data access
│       ├── grpc/               # gRPC handlers and clients
│       ├── queries/            # SQL
│       └── sqlc/               # Generated DB code
└── pkg/                        # Types other services may import

Cross-cutting concerns live in shared/: gRPC interceptors and identity propagation (contracts/), API error types with HTTP and gRPC mappings (errors/), prefixed entity IDs (id/), RabbitMQ with outbox/inbox delivery (messaging/), migrations and pooling (db/), and domain enums (constants/).

Tech stack

Go 1.27 gRPC + Protocol Buffers, via buf
MySQL 8 · PostgreSQL 16 sqlc · goose
RabbitMQ OpenTelemetry tracing
Kubernetes / EKS Tilt + minikube for local dev
Stripe AWS S3 · SES · SQS
Anthropic Claude

The project

OpenMRP is split across repositories rather than a monorepo. Everything below is Apache 2.0.

Repo What it is
api (this repo) The Go microservices, the REST API, and the OpenAPI specifications
dashboard The Next.js dashboard and customer portal, plus their Express API
ui @openmrp/ui — the React component library both frontends are built from
internal-sdk @openmrp/internal-sdk — the TypeScript client the dashboard uses
openmrp-go The Go SDK
public-docs docs.openmrp.ai — the guides plus the generated API reference

Using the API

Authenticate with a bearer API key, name the account you're acting on, and pin a version:

curl https://api.openmrp.ai/v1/catalog/items \
  -H "Authorization: Bearer $OPENMRP_API_KEY" \
  -H "OpenMRP-Account: acct_..." \
  -H "OpenMRP-Version: 1.0.forge-preview.3"
import OpenMRP from "@openmrp/sdk";

const client = new OpenMRP({ bearerToken: process.env["OPENMRP_API_KEY"] });
const items = await client.catalog.items.list();
client := openmrp.NewClient(
    option.WithBearerToken(os.Getenv("OPENMRP_API_KEY")),
    option.WithOpenMRPAccountID("acct_..."),
)
items, err := client.Catalog.Items.List(ctx, openmrp.CatalogItemListParams{})

Sandboxes, idempotency keys, pagination, ?include= expansion, request IDs, and rate limits are covered in the developer guides. AI assistants can drive the same API through the MCP server.

Running it locally

Prerequisites

make install-tools installs everything else (buf, sqlc, goose, mockgen, gotestsum, vacuum, the protoc plugins, gosec, staticcheck, goimports) at the versions pinned in tools/tool-versions.

Setup

make install-tools  # Install dev dependencies
make setup          # Start minikube and the local databases (migrations + seed data)
make dev            # Spin up the environment with Tilt

make teardown reverses it: deletes minikube, nukes the local databases, and tears down the E2E stack.

Common commands

make help lists every target. make sqlc and make mocks take service arguments — either the full directory name (core-service) or its short alias (core, auth, notification, logging → platform-service, payment → billing-service, agent, api). With no argument they run against every service.

make sqlc [service]     # Generate database code from SQL queries
make proto              # Generate Go protobuf bindings
make mocks [service]    # Generate mock implementations
make generate           # Regenerate OpenAPI specs, Stainless configs, and agent tools
make test               # Run all tests
make e2e                # Bring up the E2E stack and run the E2E tests
make lint               # gosec + staticcheck + tx audit + committed-binary check
make fmt                # Format Go sources

Local databases, seed data, and Stripe

make local-db spins up both databases in Docker containers, applies all migrations, and writes connection strings to .env automatically:

  • MySQL 8 on port 3306 — core-service (openmrp database)
  • PostgreSQL 16 on port 5432 — agent-service (openmrp_agents database)

Data is persisted in named Docker volumes so it survives container restarts. make local-db also seeds the core database with sample data (accounts, users, items, orders, etc.) via the SQL files in shared/db/seed/, and — when STRIPE_SECRET_KEY is set — creates a matching Stripe test subscription for the seeded account. Without that variable the Stripe step is skipped with a warning; run make seed-stripe later to add it.

# Re-seed core data (idempotent, safe to run multiple times)
make seed-core

# Seed with a specific plan (default: enterprise)
make seed-core ARGS="--plan starter"

# Seed the agent-service (PostgreSQL) database with e2e test data
# Migrations for it already ran as part of `make local-db`
make seed-agent-db

# Upload the seeded users' avatars to the user-photos S3 bucket
make seed-user-photos

# Connect directly
make local-db-cli   # MySQL CLI using DB_URL from .env
psql postgres://openmrp@localhost:5432/openmrp_agents

# Tear down containers (data preserved)
make local-db-down

# Tear down containers, clean up Stripe test resources, and delete all data (volumes)
# Run `make local-db` after to get clean databases with fresh migrations and seed data
make local-db-nuke
Using with Tilt / Kubernetes

Services running in minikube cannot reach localhost on the host machine. The K8s secret in infra/development/kubernetes/config/secrets.yaml uses host.minikube.internal to route traffic back to the host. These URIs match the Docker Compose databases started by make local-db:

Service URI
Core (MySQL) root:Testing123!@tcp(host.minikube.internal:3306)/openmrp
Agent (PostgreSQL) postgres://openmrp@host.minikube.internal:5432/openmrp_agents?sslmode=disable

The seed script hardcodes the Docker Compose connection details, so no .env configuration is needed — just run make local-db before make dev.

Agent endpoint-tools (optional)

Agents can invoke api-gateway endpoints flagged AgentTool: true (see make gen-agent-tools). This uses a dedicated internal api-gateway listener on port 8091, reached over the api-gateway-internal ClusterIP Service and gated by a shared token. The token is optional in dev: when it is absent the internal listener does not start and the endpoint-tools are simply unavailable (the rest of the agent works normally).

To enable it locally, add an internal-service-token secret to your infra/development/kubernetes/config/secrets.yaml:

apiVersion: v1
kind: Secret
metadata:
  name: internal-service-token
type: Opaque
stringData:
  token: "dev-internal-token" # any non-empty value in dev

Both api-gateway and agent-service already consume this secret (as INTERNAL_SERVICE_TOKEN) and the API_GATEWAY_INTERNAL_URL config value. In production the token is generated and delivered by Terraform in the private infra repo.

minikube acting up? minikube delete && minikube start clears most of it.

Contributing

Pull requests are welcome — including on the parts of this README that are wrong.

Read the pattern docs before you write. AGENTS.md and the docs in docs/patterns/ are the normative spec for this codebase — layering, API versioning, nullable fields, authorization, audit events, entity IDs, logging, comments. Where a doc and existing code disagree, the doc wins. Imitating the file next to yours is the most common way to get a change rejected.

Branch from main with a descriptive name:

git checkout -b feature/your-feature-name   # or bug/your-bug-name

Commit with Conventional Commitsrelease-please reads them to calculate the next version:

Prefix Type of change Version impact
fix: Bug fixes Patch (0.0.x)
feat: New features Minor (0.x.0)
feat!: Breaking changes Major (x.0.0)

A breaking change to the public API needs a new API version and a transformer that preserves the old shape for pinned clients. docs/patterns/api-versioning-patterns.md is the checklist — follow it, don't approximate it.

Releases. Once a PR merges, release-please maintains a Release PR that aggregates pending changes and updates the changelog; merging that PR cuts the release and deploys. This repo builds service images and pushes them to ECR, then asks the private infra repo to roll them out — nothing here holds a credential that can reach the cluster. Two consequences: infrastructure changes ship separately and must land before a release that depends on them, and manifest-only changes are a push to that repo rather than a release here. infra/development/ stays here — it is what make dev runs against, and it holds no production identifiers.

Security

Found a vulnerability? Email security@openmrp.ai rather than opening an issue — see SECURITY.md for scope and what to include.

Every sk_test_, mrp_sk_test_, whsec_ and JWT in this repository is fabricated sample or fixture data. If you find one that resolves against a real service, that is a genuine finding.

License

Apache 2.0.

"OpenMRP" and "Augno", with their logos and wordmarks, are trademarks of Augno, Inc. Section 6 of the license grants no trademark rights — see TRADEMARKS.md.

Directories

Path Synopsis
cmd
backfill-customer-role command
Command backfill-customer-role provisions the global "Customer" role in the database and assigns it to customer-portal account users.
Command backfill-customer-role provisions the global "Customer" role in the database and assigns it to customer-portal account users.
dedupe-inventory-allocations command
Command dedupe-inventory-allocations removes duplicate inventory allocation rows written by replayed production-step scans, and returns the receipts they falsely closed out to `available`.
Command dedupe-inventory-allocations removes duplicate inventory allocation rows written by replayed production-step scans, and returns the receipts they falsely closed out to `available`.
genid command
print-version command
internal
services
agent-service/internal/domain/mock/client
Package clientmock is a generated GoMock package.
Package clientmock is a generated GoMock package.
agent-service/internal/domain/mock/factory
Package factorymock is a generated GoMock package.
Package factorymock is a generated GoMock package.
agent-service/internal/domain/mock/mediator
Package mediatormock is a generated GoMock package.
Package mediatormock is a generated GoMock package.
agent-service/internal/domain/mock/repository
Package repositorymock is a generated GoMock package.
Package repositorymock is a generated GoMock package.
agent-service/internal/domain/mock/service
Package servicemock is a generated GoMock package.
Package servicemock is a generated GoMock package.
agent-service/internal/infrastructure/httpgateway
Package httpgateway provides an HTTP client that invokes api-gateway endpoints over the gateway's trusted internal listener on behalf of an agent identity.
Package httpgateway provides an HTTP client that invokes api-gateway endpoints over the gateway's trusted internal listener on behalf of an agent identity.
api-gateway/cmd command
api-gateway/endpoints/portal-domains
Package portaldomainep implements the customer portal custom-domain management endpoints, backed by the core-service CorePortalDomainService gRPC client.
Package portaldomainep implements the customer portal custom-domain management endpoints, backed by the core-service CorePortalDomainService gRPC client.
api-gateway/endpoints/portal-registration-sessions
Package portalregsessionep implements the buyer customer-portal registration-session endpoints, backed by the core-service CoreService gRPC client.
Package portalregsessionep implements the buyer customer-portal registration-session endpoints, backed by the core-service CoreService gRPC client.
api-gateway/internal/chatmap
Package chatmap converts notification-service chat proto messages into gateway API resources.
Package chatmap converts notification-service chat proto messages into gateway API resources.
api-gateway/internal/domain/mock/publisher
Package publishermock is a generated GoMock package.
Package publishermock is a generated GoMock package.
api-gateway/internal/resourceloaders
Package resourceloaders holds the gRPC-backed loaders used by the api-gateway resourcekit include resolver.
Package resourceloaders holds the gRPC-backed loaders used by the api-gateway resourcekit include resolver.
api-gateway/internal/resourceregistry
Package resourceregistry contains the init()-time resourcekit.Definition registrations for every resource the api-gateway resolves includes against.
Package resourceregistry contains the init()-time resourcekit.Definition registrations for every resource the api-gateway resolves includes against.
api-gateway/internal/versiontransforms
Package versiontransforms registers the version.Transformer chain that the api-gateway uses to keep older API versions working.
Package versiontransforms registers the version.Transformer chain that the api-gateway uses to keep older API versions working.
api-gateway/pkg/resource
! Note: this will be refactored in the future - okay to leave as is.
! Note: this will be refactored in the future - okay to leave as is.
api-gateway/pkg/resourcekit
Package resourcekit is the canonical registry for API resources.
Package resourcekit is the canonical registry for API resources.
auth-service/internal/domain/mock/client
Package clientmock is a generated GoMock package.
Package clientmock is a generated GoMock package.
auth-service/internal/domain/mock/factory
Package factorymock is a generated GoMock package.
Package factorymock is a generated GoMock package.
auth-service/internal/domain/mock/mediator
Package mediatormock is a generated GoMock package.
Package mediatormock is a generated GoMock package.
auth-service/internal/domain/mock/publisher
Package publishermock is a generated GoMock package.
Package publishermock is a generated GoMock package.
auth-service/internal/domain/mock/repository
Package repositorymock is a generated GoMock package.
Package repositorymock is a generated GoMock package.
auth-service/internal/domain/mock/service
Package servicemock is a generated GoMock package.
Package servicemock is a generated GoMock package.
billing-service/internal/domain/mock/client
Package clientmock is a generated GoMock package.
Package clientmock is a generated GoMock package.
billing-service/internal/domain/mock/factory
Package factorymock is a generated GoMock package.
Package factorymock is a generated GoMock package.
billing-service/internal/domain/mock/mediator
Package mediatormock is a generated GoMock package.
Package mediatormock is a generated GoMock package.
billing-service/internal/domain/mock/repository
Package repositorymock is a generated GoMock package.
Package repositorymock is a generated GoMock package.
billing-service/internal/domain/mock/service
Package servicemock is a generated GoMock package.
Package servicemock is a generated GoMock package.
core-service/cmd/backfill-operating-calendars command
Command backfill-operating-calendars gives existing accounts the shipping and receiving calendars new accounts are provisioned with.
Command backfill-operating-calendars gives existing accounts the shipping and receiving calendars new accounts are provisioned with.
core-service/internal/calendarseed
Package calendarseed gives a new account the operating calendars a ship-by commitment is resolved against.
Package calendarseed gives a new account the operating calendars a ship-by commitment is resolved against.
core-service/internal/domain/mock/client
Package clientmock is a generated GoMock package.
Package clientmock is a generated GoMock package.
core-service/internal/domain/mock/factory
Package factorymock is a generated GoMock package.
Package factorymock is a generated GoMock package.
core-service/internal/domain/mock/mediator
Package mediatormock is a generated GoMock package.
Package mediatormock is a generated GoMock package.
core-service/internal/domain/mock/publisher
Package publishermock is a generated GoMock package.
Package publishermock is a generated GoMock package.
core-service/internal/domain/mock/repository
Package repositorymock is a generated GoMock package.
Package repositorymock is a generated GoMock package.
core-service/internal/domain/mock/service
Package servicemock is a generated GoMock package.
Package servicemock is a generated GoMock package.
core-service/internal/forecast
Package forecast holds OpenMRP's standard monthly demand forecaster.
Package forecast holds OpenMRP's standard monthly demand forecaster.
core-service/internal/hubspotsync
Package hubspotsync orchestrates pushing OpenMRP sales orders to HubSpot as Closed-Won deals, upserting the associated company and contact along the way.
Package hubspotsync orchestrates pushing OpenMRP sales orders to HubSpot as Closed-Won deals, upserting the associated company and contact along the way.
core-service/internal/infrastructure/hubspot
Package hubspot implements a thin HTTP client over the HubSpot CRM v3/v4 API, scoped to the company/contact/deal operations the sales-order sync needs.
Package hubspot implements a thin HTTP client over the HubSpot CRM v3/v4 API, scoped to the company/contact/deal operations the sales-order sync needs.
core-service/internal/infrastructure/vercel
Package vercel implements the portal domain provider on top of the Vercel Domains API.
Package vercel implements the portal domain provider on top of the Vercel Domains API.
core-service/internal/scheduling
Package scheduling is the production schedule solver.
Package scheduling is the production schedule solver.
core-service/internal/stripesync
Package stripesync reconciles OpenMRP customers with their counterparts in a merchant's connected Stripe account.
Package stripesync reconciles OpenMRP customers with their counterparts in a merchant's connected Stripe account.
notification-service/internal/domain/mock/factory
Package factorymock is a generated GoMock package.
Package factorymock is a generated GoMock package.
notification-service/internal/domain/mock/repository
Package repositorymock is a generated GoMock package.
Package repositorymock is a generated GoMock package.
notification-service/internal/domain/mock/service
Package servicemock is a generated GoMock package.
Package servicemock is a generated GoMock package.
notification-service/internal/ratelimit
Package ratelimit provides a small in-memory token-bucket limiter used to throttle abusive messaging actors (message send, conversation creation).
Package ratelimit provides a small in-memory token-bucket limiter used to throttle abusive messaging actors (message send, conversation creation).
notification-service/internal/reaper
Package reaper holds the background retention worker for the messaging substrate.
Package reaper holds the background retention worker for the messaging substrate.
notification-service/internal/scheduler
Package scheduler holds the background worker that delivers due scheduled messages.
Package scheduler holds the background worker that delivers due scheduled messages.
platform-service/internal/domain/mock/factory
Package factorymock is a generated GoMock package.
Package factorymock is a generated GoMock package.
platform-service/internal/domain/mock/repository
Package repositorymock is a generated GoMock package.
Package repositorymock is a generated GoMock package.
platform-service/internal/domain/mock/service
Package servicemock is a generated GoMock package.
Package servicemock is a generated GoMock package.
shared
appnav
Package appnav exposes the dashboard's page catalog to the API — which pages the app has, and which API object type each record detail page shows.
Package appnav exposes the dashboard's page catalog to the API — which pages the app has, and which API object type each record detail page shows.
cloud/sqs
Package sqs is a thin wrapper over the AWS SQS SDK for the consumers that poll a queue (currently the inbound-email bridge).
Package sqs is a thin wrapper over the AWS SQS SDK for the consumers that poll a queue (currently the inbound-email bridge).
db
env
errors
Package apierror defines the structured error types used across all services.
Package apierror defines the structured error types used across all services.
excel
Package excel builds spreadsheet workbooks from a declarative description of columns and rows, with no knowledge of any domain type.
Package excel builds spreadsheet workbooks from a declarative description of columns and rows, with no knowledge of any domain type.
id
lease
Package lease provides a distributed single-holder lease primitive backed by a SQL table.
Package lease provides a distributed single-holder lease primitive backed by a SQL table.
logging
Package logging provides structured logging utilities for gRPC services.
Package logging provides structured logging utilities for gRPC services.
messaging
Package messaging provides rabbitMQ integration, outbox/inbox patterns, and background workers for reliable asynchronous communication between microservices.
Package messaging provides rabbitMQ integration, outbox/inbox patterns, and background workers for reliable asynchronous communication between microservices.
retry
Package retry provides configurable retry logic with exponential backoff and jitter.
Package retry provides configurable retry logic with exponential backoff and jitter.
rpc
safeconv
Package safeconv provides safe integer conversion functions that clamp values at the target type's boundaries instead of silently overflowing.
Package safeconv provides safe integer conversion functions that clamp values at the target type's boundaries instead of silently overflowing.
sanitize
Package sanitize provides utilities for masking sensitive string values (API keys, tokens, secrets) in log output, error messages, and user-facing responses.
Package sanitize provides utilities for masking sensitive string values (API keys, tokens, secrets) in log output, error messages, and user-facing responses.
timeutil
Package timeutil provides helpers for parsing timestamp strings used throughout the platform's data layer.
Package timeutil provides helpers for parsing timestamp strings used throughout the platform's data layer.
tracing
Package tracing provides OpenTelemetry tracing initialization and helpers for all microservices.
Package tracing provides OpenTelemetry tracing initialization and helpers for all microservices.
validate
Package validate provides request-level input validation for the platform.
Package validate provides request-level input validation for the platform.
tests

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL