What is a connection?

A production connection is one distinct (production service, consuming organization) pair with at least one active or suspended grant.

What consumes capacity
SituationConnections
Several workloads, replicas, certificate renewals or re-enrollments for the same service and partner1
The same partner on a second production service+1
A second partner on the same service+1
Your own organization as the consumer of your own service1 (counts like any partner)
Suspended grantKeeps its slot, shown as reserved
Sandbox grants, pending invitations, withdrawn or expired grants0

The limit is enforced atomically when a grant activates: accepting an invitation that would create a new pair beyond your capacity fails with 409 capacity_exceeded. Adding workloads to an existing pair never does.

Plans

Plans
SKUPlanCapacityPrice
team_10Team · 10 connections10USD 299 / month
team_50Team · 50 connections50USD 799 / month
NoneEnterprise and channelContractedAnnual contract or invoice terms through your Sectigo account team

The sandbox is free, needs no card, and consumes nothing. Invited partner admins participate in a paying sponsor’s relationship without buying a plan.

Buy with Stripe Checkout

Requires the billing_admin role in the organization. An owner must be explicitly assigned it (see Organization). The server maps the SKU to a Stripe price, binds your Stripe customer and fixes the redirect URLs; the client never sends a price.

POST /v1/billing/checkout-sessions
POST https://app.mutualtrust.io/v1/billing/checkout-sessions Idempotency-Key: 5c0e-checkout-team10 X-CSRF-Token: <csrf_token> Content-Type: application/json { "org_id": "org_01jcqa7m2k9x4v8r3t6p5w2h7n", "sku": "team_10" }
201 Created
{ "operation_id": "chk_01jcqe6j8k0m2n4p6q8r0s2t4v", "url": "https://checkout.stripe.com/c/pay/cs_live_…", "mode": "live" }

Redirect the user to url. Card details stay with Stripe. Stripe returns to https://app.mutualtrust.io/#/billing?org=…&checkout=chk_…, where the portal shows pending until a verified Stripe event establishes the subscription. Entitlement is never inferred from the browser redirect.

Checkout errors
StatusCodeMeaning
403forbiddenYou lack billing_admin for this organization.
409subscription_existsThe organization already has an active or in-grace subscription. Change capacity in the billing portal.
409stripe_errorStripe rejected the request; the message is Stripe’s.
503billing_unconfigured / plan_unavailableThat plan is not offered on this deployment. Contact your Sectigo account team for contracted plans.
503stripe_unavailableStripe is unavailable; retry shortly.

Subscription and entitlement states

Mutual Trust keeps the Stripe subscription status and its own entitlement state separately:

Entitlement mapping
Stripe statusEntitlementEffect
active, trialingactiveNew connections allowed up to capacity.
past_due, unpaidgrace for 14 days, then blockedDuring grace existing connections continue, but no new connection can be added. Owners and billing admins see a past-due notice with the grace end date.
incomplete, paused, otherblockedNew grants are blocked. Revocation, evidence and export remain available.
canceled, incomplete_expiredendedNo capacity.

Grace advances with time even without a new Stripe event. Expiry, deliberate offboarding and emergency security actions are independent of billing.

Manage billing in the Stripe portal

POST /v1/billing/portal-sessions
POST https://app.mutualtrust.io/v1/billing/portal-sessions X-CSRF-Token: <csrf_token> Content-Type: application/json { "org_id": "org_01jcqa7m2k9x4v8r3t6p5w2h7n" }
201 Created
{ "url": "https://billing.stripe.com/p/session/live_…" }

Use the hosted portal to update a payment method, download invoices and change or cancel your plan. A billing admin can do this without any access to trust configuration.

Billing summary

GET /v1/organizations/{id}/billing (roles billing_admin, owner or auditor):

200 OK
{ "configured": true, "mode": "live", "subscription": { "id": "sub_01jcqe7k9m1n3p5q7r9s1t3v5w", "stripe_status": "active", "entitlement_state": "active", "connections": 10, "current_period_end": "2026-12-14T15:52:00Z", "grace_ends_at": null, "cancel_at": null, "currency": "usd", "plan_name": "Team · 10 connections", "unit_amount": 29900, "interval": "month" }, "usage": { "active": 3, "reserved": 1, "used": 4, "capacity": 10, "remaining": 6 }, "invoices": [ { "number": "MT-0001", "status": "paid", "currency": "usd", "total": 29900, "amount_remaining": 0, "due_at": "2026-11-14T15:52:00Z", "paid_at": "2026-11-14T15:52:09Z", "hosted_invoice_url": "https://invoice.stripe.com/i/…", "issued_at": "2026-11-14T15:52:00Z" } ], "plans": [ { "sku": "team_10", "name": "Team · 10 connections", "connections": 10, "unit_amount": 29900, "currency": "usd", "interval": "month" }, { "sku": "team_50", "name": "Team · 50 connections", "connections": 50, "unit_amount": 79900, "currency": "usd", "interval": "month" } ], "grace_days": 14 }

Amounts are integer minor units with a lowercase ISO 4217 currency.

How payments are processed

  • Stripe sends events to POST https://api.mutualtrust.io/webhooks/stripe. The signature is verified on the raw body (5-minute tolerance) before parsing; events are stored in a de-duplicating inbox and acknowledged quickly.
  • A worker re-reads the current Stripe subscription, invoice or balance objects and applies idempotent transitions, so duplicated, delayed or reordered deliveries are safe.
  • Every 6 hours a reconciler re-reads all known subscriptions and imports balance transactions and payouts, covering lost webhooks.