Provisioning API

Sell GreenmorMail to your own customers, from your own panel, on your own billing.

You keep the customer relationship, the login and the payment gateway. We run the mail infrastructure and invoice you wholesale, weekly. This API is how your systems create and manage mailboxes without anyone touching our dashboard.

Base URL

https://api.greenmormail.com/api/v1

Authentication

Create keys in your partner panel under Provisioning API. A key is displayed once.

curl https://api.greenmormail.com/api/v1/ping \
  -H "Authorization: Bearer gmp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Keys carry scopes and a mode:

ModeWhat it does
testProvisions for real, so you can build and run CI against it — but never creates a charge.
liveProvisions and bills.
Build against a test key first. Nothing you do with one will ever appear on an invoice.

A complete first integration

KEY="gmp_…"
API="https://api.greenmormail.com/api/v1"

# 1. the customer you are selling to
curl -s -X POST $API/customers -H "Authorization: Bearer $KEY" \
     -H "Idempotency-Key: cust-1001" -H "Content-Type: application/json" \
     -d '{"email":"owner@acme.com","name":"Acme Ltd","external_ref":"YOUR-CRM-1001"}'

# 2. their domain — the response carries the DNS records they must publish
curl -s -X POST $API/domains -H "Authorization: Bearer $KEY" \
     -H "Idempotency-Key: dom-1001" -H "Content-Type: application/json" \
     -d '{"domain":"acme.com","customer_id":247}'

# 3. once those records are live
curl -s -X POST $API/domains/acme.com/verify -H "Authorization: Bearer $KEY"

# 4. the mailbox
curl -s -X POST $API/mailboxes -H "Authorization: Bearer $KEY" \
     -H "Idempotency-Key: mb-1001" -H "Content-Type: application/json" \
     -d '{"domain":"acme.com","local_part":"sales","password":"…","external_ref":"YOUR-SEAT-55"}'

Put your own identifiers in external_ref on customers, domains and mailboxes. It comes back on every read and on webhooks, so you never need a mapping table.

Idempotency

Every POST requires an Idempotency-Key. Retrying with the same key returns the original response rather than provisioning twice — safe after a timeout, a redeploy or a queue replay. Reusing a key with a different body is refused.

Errors

{ "error": { "code": "domain_not_verified", "message": "…", "field": "domain" } }

Branch on error.code. It is stable; the message is not.

CodeMeaning
domain_not_verifiedPublish the DNS records, then call verify.
email_already_registeredThat address exists somewhere on the platform. Use a different contact address.
domain_already_registeredSomeone already holds that domain here.
mailbox_existsThat address is already in use.
seat_limit_reachedYour account's mailbox ceiling. Talk to us to raise it.
account_write_blockedUnpaid dues: provisioning is paused. Your customers' mail keeps flowing.
insufficient_scopeThe key lacks the scope for this call.
rate_limitedBack off; see Retry-After.

Webhooks

Your panel is the only interface your customer sees, so subscribe rather than poll. Register an HTTPS endpoint and you receive domain.verified, mailbox.expiring, mailbox.suspended and mailbox.quota_threshold.

Verify every delivery — the signature is an HMAC-SHA256 of the raw body, keyed by the secret shown when you registered the endpoint:

X-Greenmor-Signature: sha256=<hex>

Delivery is at-least-once with backoff, so deduplicate on event_id.

We never email your customers

Mailboxes you create through this API are yours end to end. The platform sends nothing to your customers — no renewal reminders, no expiry warnings, no deletion notices. You hear about expiry through the mailbox.expiring webhook, and the wording your customer receives is entirely yours.

Rate limits

CallsLimit
Reads600 / minute
Writes60 / minute
Domain verification10 / hour (it performs live DNS lookups)

A throttled response is 429 with Retry-After and X-RateLimit-*.

Regions

One key belongs to one partnership, and a partnership belongs to one region. Serving customers in two regions means two partnerships, two sets of keys and two invoices. GET /ping tells you which region you are on, and every mailbox response carries the IMAP, SMTP and webmail hosts your customers should actually use — they differ per region, so never hard-code them.

Already running WHMCS?

Don't build a panel. The GreenmorMail WHMCS module wires ordering, suspension, upgrades and termination straight through to this API — one WHMCS service is one mailbox. Drop it in modules/servers/, paste your key into the server's Access Hash, and sell.

Point the server at a test key while you set the product up. You can order, suspend and terminate for real without a single charge.

Full reference

The complete OpenAPI 3.1 specification: openapi.yaml. Load it into Postman, Insomnia, or a client generator.