MintOffice — Technical¶
The technical companion to the MintOffice operator guide. The operator guide walks you through the dashboard wizard; this page is for the developer-facing parts: which repositories you own, what each one controls, and how a customer's "Buy" click ends up as a running agent on your own domain.
customization template partner-portal-example Brand Partner API reference
How the pieces fit together¶
A white-label MintOffice setup is three layers, owned by three different people:
┌──────────────────────────┐ ┌──────────────────────────┐ ┌──────────────────────────┐
│ Your storefront │ │ MintOffice (central) │ │ Each customer's agent │
│ (partner-portal-*) │──▶│ mint.mintbot.ai │──▶│ agent1.yourbrand.com │
│ yourbrand.com │ │ + deploy worker │ │ (one VPS per customer) │
└──────────────────────────┘ └──────────────────────────┘ └──────────────────────────┘
you host mintbot hosts mintbot hosts (per agent)
- Storefront — your customer-facing website. Shows plan cards, takes the "Buy" click, forwards the order to MintOffice, receives webhook events. You fork the example, brand it, host it on a domain you control.
- MintOffice central — runs on
mint.mintbot.ai. Owns the Brand Partner API, the Stripe integration, the per-partner secret vault (Telegram bot token, Zone.ee API key, …), the deploy worker, the revenue ledger. Mintbot operates this for every partner; you never run it yourself. - Each customer's agent — a dedicated VPS spun up by the deploy worker
when an order is paid. Central deploys the standard, unbranded base agent
itself; then the VPS clones your agent customization repo and runs it
locally to apply your persona, panel theme, and any extra tooling.
Central never executes your repo — only the agent's own VPS does. The
customer chats through your Telegram bot or the web panel on a subdomain
of your apex (
agent1.yourbrand.com).
The two repositories you own¶
White-label branding sits in two separate repositories, each with a different concern. You own and host them independently, on whatever cadence makes sense for your brand.
1. Agent customization repo — what each customer's agent looks like¶
Your agent customization repo controls the persona the agent uses, the panel theme (CSS/JS) the customer sees in the browser, and any extra tooling or client-specific setup you want layered on top of the base agent. Unlike the old "template fork" model, central never clones or runs this repo. Instead, central does the full standard deploy itself, and then the agent's own VPS clones your repo and runs it locally — so it's your code, running under your control, on the agent's machine.
| What it is | A GitHub repository whose root contains two scripts — install.sh and update.sh — plus any assets (theme files, persona text, tool definitions) those scripts install. You own it entirely; there is no allow-list and no central bake step. |
| Starting point | mintbot-ai/agent-template — a ready-to-fork model repo. Root contains install.sh / update.sh plus theme/ (panel CSS/JS) and persona/ (brand voice) assets and a lib/common.sh of helpers. Ships with a placeholder ExampleAI brand you rename. Fork it, swap in your branding, push, then point the wizard at your fork's HTTPS URL. |
| Wired into MintOffice via | Dashboard → Settings → Agent customization repo → paste your repo's HTTPS URL. Central renders the URL into the agent VPS environment; the VPS calls git clone after the standard deploy is healthy. |
| Fail-isolated | A missing, failing, or slow script never fails the deploy, never blocks the base-package update, and never breaks the customer's agent. Failures are logged on the VPS and surfaced to you — they never reach the end customer. |
The install.sh / update.sh contract¶
The repo root is a contract: two scripts that the agent's own VPS runs at well-defined points in its lifecycle.
install.sh— runs once, on the agent's own VPS, after the standard deploy has finished and the agent is healthy. This is where you install your own customization: drop in your theme, adjust the persona, register extra tools, do any client-specific setup. The agent is already live and serving when this runs;install.shlayers your brand on top.update.sh— runs after every package update on the VPS. Optional. When the agent self-updates its base package, it then runs yourupdate.shso you can re-apply or adjust your own layer on top of the new base. Leave the file out if your customization survives base updates untouched.
Update ordering
On every update, the base package is applied first — this is the
white-label base agent, kept on the upstream update path — and then
your update.sh runs on top of it. Your layer is always re-applied
against the newest base, never the other way around.
Fail-isolation — your scripts can't break the customer's agent
The customization scripts run on a best-effort basis and are completely
fenced off from the signed base. If install.sh or update.sh is
missing, errors out, or runs slowly:
- the deploy still succeeds and the agent stays healthy,
- the base-package update is never blocked or reverted,
- the failure is logged on the VPS and surfaced to you, the operator — it never reaches the end customer.
There are no central "contract tests" and no aborted deploys, because central never runs your code. The trade-off: a broken script silently leaves the agent on the plain base rather than your branded layer, so test your repo on a DEV deploy before pointing live agents at it.
Security — this is your responsibility zone
Central never executes your repo. Only the agent's own VPS clones and runs it, with the same privileges the agent itself runs with on that box (your scripts run on your customer's own VPS, not on any shared infrastructure). The repo URL is GitHub HTTPS only, validated before it is stored; the clone is shallow, size-capped, and time-bounded, and your scripts run with a timeout and secrets withheld from their environment. Everything your scripts do is in your own responsibility zone — clearly fenced off from the signed base package that central controls. Because end users must never see the underlying base brand, keep your persona and theme unbranded-to-mintbot and present only your brand.
2. Storefront portal — what your customer sees before buying¶
The storefront is the website where customers land, browse plans, click Buy, get redirected to Stripe, and come back to a thank-you page. It also receives MintOffice's webhook deliveries so your own systems know when an order is paid, when its agent is ready, when it expires.
| Reference repo | mintbot-ai/partner-portal-example — MIT-licensed FastAPI + SQLite, Dockerised, ships with an ExampleAI brand you swap out. Implements landing, /buy, thank-you/cancel pages, signed webhook receiver, HTTP-Basic-auth /admin event browser. |
| Wired into MintOffice via | Dashboard → Settings → API access → set Webhook URL to https://<your-host>/webhooks/mintoffice and copy the signing secret into the portal's .env. |
| You host it | Anywhere with HTTPS — your own VPS, a serverless platform, or alongside one of your customer agents. Mintbot does not host the storefront. |
The example portal is small (a few hundred lines of FastAPI) and the
README walks the rebranding through every touchpoint — .env config,
CSS variables, copy, translations. Fork it, swap in your brand, and
host it on a domain you control.
End-to-end deploy flow¶
What actually happens when a customer clicks Buy on your storefront:
1. Customer ⟶ POST /buy on your storefront
│
▼
2. Storefront ⟶ POST /api/v1/orders to MintOffice (with your API key)
│ returns checkout_url
▼
3. Customer ⟶ Stripe Checkout (mintbot's Stripe account)
│
▼
4. Stripe webhook ⟶ MintOffice marks order paid
│ fires order.paid webhook to your portal
│ enqueues a deploy job
▼
5. Deploy worker ⟶ spins up a VPS
⟶ runs the full standard deploy (the white-label base agent)
⟶ provisions DNS A-record via your Zone.ee credentials
⟶ issues Let's Encrypt cert
⟶ waits until the agent is healthy
│
▼
6. Agent VPS ⟶ clones your agent customization repo (URL rendered in by central)
⟶ runs install.sh once, on the agent's own VPS
⟶ applies your persona / theme / extra tooling on top
│ (a failing or missing script is logged, never fatal)
▼
7. agent.ready webhook ⟶ delivered to your portal
⟶ branded handoff email sent (pigeon@mintbot.ai)
⟶ customer can open https://agent1.yourbrand.com
Steps 2 and 4 happen over the Brand Partner API. Step 5 is entirely inside MintOffice — your storefront doesn't need to know how the VPS or Let's Encrypt work. Step 6 runs your code on the agent's own VPS; central never executes it. Either way, your storefront just receives the lifecycle events.
Ongoing updates¶
After launch, each agent self-updates its base package on the upstream cadence. The ordering is fixed:
1. Agent VPS ⟶ applies the new base package update first
│ (the white-label base agent)
▼
2. Agent VPS ⟶ runs your agent customization repo's update.sh on top
│ re-applies / adjusts your layer against the new base
▼
(update.sh is optional; a failing or missing script is logged,
never blocks or reverts the base update, never breaks the agent)
Brand Partner API¶
The REST surface MintOffice exposes for your storefront (and any other integration of yours) lives on its own page:
Quick mental model:
- Auth —
Authorization: Bearer mo_live_…. One key per partner; rotate from Settings → API access. - Writes are idempotent — every
POSTtakes anIdempotency-Keyheader; retrying with the same key replays the original response. - Reads are cheap —
GET /api/v1/settingsreturns your full non-secret configuration (modes, apex domain, pricing, readiness) for use by your storefront or an installer agent. - Lifecycle is webhook-driven —
order.created,order.paid,agent.ready,agent.failed,agent.expired. HMAC-SHA256 signed, up to 7 retries. - DNS is proxied —
POST /api/v1/dns/recordsupserts an A-record on your apex without your portal ever holding the upstream provider's API key. MintOffice keeps the Zone.ee credential encrypted server-side and makes the upstream call on your behalf.
What MintOffice owns vs. what you own¶
A quick reference for "where does this fact live, and who can change it":
| Fact / asset | Lives in | You can change it via |
|---|---|---|
| Customer plan prices | MintOffice DB | Dashboard → Settings → Pricing |
| Agent persona (SOUL.md) | Your agent customization repo, applied on the VPS by install.sh / update.sh |
Push to the repo |
| Panel theme (CSS / JS) | Your agent customization repo, applied on the VPS by install.sh / update.sh |
Push to the repo |
| Storefront copy, layout, plan cards | Your storefront repo | Push and redeploy your portal |
| Customer-facing brand name in emails | MintOffice (driven by product_name per order, with your apex as fallback) |
Set per-order on POST /api/v1/orders |
| Telegram bot token, Zone.ee API key | MintOffice secret vault (encrypted) | Dashboard → Settings → Domain / Bot |
| Stripe API integration | MintOffice (mintbot's Stripe account) | Not partner-configurable |
| Customer's running agent (SOUL.md, config) | The agent's own VPS | The agent itself (after initial seed) |
| Revenue ledger | MintOffice DB | Read-only via GET /api/v1/revenue |
The agent-VPS-first split matters: central deploys the standard base agent
and steps back. Your persona and theme are applied on the VPS by your
own install.sh (and re-applied by update.sh after each base update) —
central never bakes them in. From there, the agent owns its SOUL.md and
config.yaml: a customer is free to ask their agent to change its persona,
set a BYOK key, switch model — without touching your agent customization repo or
your storefront.
Where to go from here¶
- You're the operator setting up your partner account — start with MintOffice — Overview. It walks the dashboard wizard step by step.
- You're building the integration — start with the
Brand Partner API reference, then clone
partner-portal-exampleas a working baseline. - You're rebranding the agent itself — fork
agent-template, which already has aninstall.sh/update.shat its root plus theme and persona assets. Swap in your branding, push, then point the wizard at your fork's HTTPS URL. - You want to see all of this running —
agent99.ccis a live mintbot.dev partner. Place a test order there to see the same flow you'll be setting up.