Create Accountor Login
Docs

The Billing API

Part of the MountDev Ops Workspace documentation. Updated October 29, 2026

MountDev Ops Workspace documentation | Updated October 29, 2026

The Billing API lets your own systems change what you pay MountDev for, such as adding Maintenance to a client's website or adding a new website with Hosting, with the same prices, rules, and records as your screens. Every change is a quote first, and nothing happens until you authorize that exact quote. MountDev never charges your card or bank from the API: an authorized change goes on your next invoice, the same way Add a Service does.

It uses the same address and version as the Reporting API, with keys of its own.

Billing Keys

A billing key is its own kind of API key, made on Settings, Connections, API Keys with Kind set to Billing (action core.api_keys.create). Owners and admins can make one, and the person who makes it must be allowed to approve paid work for your account; if they no longer are, the key stops working until someone who is makes a new one.

  • Services it may add: any of hosting, maintenance, and performance. A change for any other service is refused.
  • Monthly limit (optional): in cents. A change is refused when what this key's changes added to your monthly total this month, including changes waiting for an owner, would pass it.
  • A billing key starts with mdo_bill_, so your systems and secret scanners can tell it apart. It is shown once, only its fingerprint is kept, and it can be limited to addresses, rotated (action core.api_keys.rotate), and revoked (action core.api_keys.revoke) like any key.
  • A billing key can never read: not your records, not the Reporting API. A reporting key can never change billing.

Owner Approval

On Settings, Connections, API Keys, an owner can turn on API billing changes need owner approval in the portal (action core.api_keys.billing_approval). With it on, an authorized change waits (pending_owner) until an owner approves or refuses it in your account, and it is applied as the owner who approved it.

Owners see the waiting changes at the top of Billing, under API Changes Waiting for You: each one in the exact words it was quoted with, the monthly total now and after, and the name of the key that asked. Approve and Refuse each ask once more before anything happens. Nothing is charged when you approve; each service is billed from the day it is running, prorated, on your next invoice.

The Addresses

Method and addressWhat it does
POST billing/changesAsk for a quote. Body: { "action": "add_service", "site": "<id>", "services": [ "maintenance" ] }, or { "action": "add_site", "domain": "example.com", "services": [ "hosting", "maintenance" ] }
POST billing/changes/<id>/authorizeAuthorize that quote. Send an Idempotency-Key header
GET billing/changes/<id>One change and where it is
GET billing/changesYour changes, newest first (limit up to 100, 25 at first; cursor)

A website's <id> is the id the Reporting API's GET sites gives it.

A Quote

{ "id": "chg_3f9a1c0d2b7e4f8a9c1d2e3f", "action": "add_service", "status": "quoted", "site": { "id": "1042", "host": "example.com" }, "lines": [ { "service": "performance", "name": "Managed WordPress Performance", "monthly_cents": 3000, "first_month": "prorated from the day it is running" } ], "monthly_before_cents": 5000, "monthly_after_cents": 8000, "monthly_change_cents": 3000, "first_month_estimate_cents": 300, "today_cents": 0, "credit_cents": 0, "effective": "when_running", "wording": "I authorize adding these services to example.com at $30.00 a month, ...", "expires_at": "2026-10-29T18:15:00.000Z" }

  • lines are exactly what is added, at today's prices. monthly_before_cents and monthly_after_cents are the website's monthly total before and after.
  • Nothing is billed today (today_cents is 0). Each service is billed from the day it is running, prorated for that month, on your next invoice (effective is when_running; first_month_estimate_cents is that month's part if it were running today).
  • wording is the exact text your authorization agrees to. It is kept with the authorization.
  • A quote expires 15 minutes after it is made (expires_at). Ask for a new one after that.

Authorizing

POST /account/api/v1/billing/changes/chg_3f9a1c0d2b7e4f8a9c1d2e3f/authorize Authorization: Bearer mdo_bill_... Idempotency-Key: order-2026-10-29-0001

  • The answer is the change with status applied (done: the services are on your account and on your next invoice), or pending_owner (waiting for an owner's approval).
  • Send the same Idempotency-Key again and you get the same answer, and nothing is done twice. A quote that was already authorized with another key is refused.
  • Refused, with the reason: an expired quote (410, expired), a price or website that changed since the quote (409, quote_changed), the key's monthly limit (403, over_limit), a service the key may not add (403, forbidden), and a closed account (409, closed).
  • Each authorization is kept with the quote's exact wording, the time, the address and browser it came from, the key, and the change, the same way an authorization in your account is kept.

Limits

Each billing key may make 20 calls a minute, ask for up to 30 quotes an hour, and authorize up to 50 changes a day. Over a limit, a call is refused with 429 and "code": "rate_limited".

Events

Webhooks can hear billing.change.quoted, billing.change.authorized (with data.status authorized or pending_owner), and billing.change.applied, each with data.change_id, data.action, and data.monthly_cents (see Webhooks).

Coming Next Planned

  • Removing a service or a website: it stops at once, the unused days are credited, prorated, on your next invoice, and the quote shows the credit and the days it covers. Removing Hosting takes the website offline, so it needs "confirm_offline": true, and its final backup is kept for 180 days.
  • Asking MountDev to handle an issue for you (Have Us Handle This), at its listed price.

Ask Us Anything

We’d love to hear from you!