Everything the console does, the API does.
Available on Hosted Pro and to partners. REST over HTTPS, JSON, OAuth 2.0 client credentials or scoped API keys, webhooks with signed payloads. Designed so an IT provider can automate onboarding and a compliance platform can pull evidence. Reference outline — endpoints finalize at general availability
Base URL and versioning
https://api.pxcmail.com/v1/
Versions are in the path. Breaking changes ship as a new version with at least 12 months of overlap; additive changes (new fields) are not breaking. Every response carries X-PXC-Version and X-Request-Id.
Authentication
- API keys: created in Console → Security → API keys with scopes (
read:audit,read:archive,write:users,write:policy,write:holds,read:reports,partner:*); shown once; rotatable; IP allowlist optional. Sent asAuthorization: Bearer <key>. - OAuth 2.0 client credentials for partner integrations acting across client organizations; tokens valid 60 minutes; organization selected with
X-PXC-Org. - All calls TLS 1.2+; keys never grant message-content access unless the
read:archivescope is granted by an Owner with dual approval; such access is logged like console access.
Resources
| Resource | Endpoints | Notes |
|---|---|---|
| Organizations | GET /organizations/{id} · PATCH (name, profile, security officer) · partners: GET /organizations, POST (provision) | Provisioning returns agreement links to sign; status moves pending_agreement → pending_dns → active |
| Domains | GET/POST /organizations/{id}/domains · GET /domains/{id}/dns (records + live check) · POST /domains/{id}/verify | Returns SPF, DKIM CNAMEs, MAIL FROM, MX, DMARC suggestions |
| Connections | GET/POST /organizations/{id}/connections (google_relay, m365_connector, mx) · POST /connections/{id}/rotate-credential | Credential returned once |
| Users | GET/POST/PATCH/DELETE /organizations/{id}/users · POST /users/{id}/mfa/reset · POST /users/{id}/app-passwords · GET /users/{id}/devices · POST /devices/{id}/wipe | Seats counted from active users; directory sync marks source |
| Policies | GET /organizations/{id}/policy · PUT (full document, versioned) · POST /policy/test (sample message → actions) · GET /policy/versions · POST /policy/rollback | Policy document schema published as JSON Schema |
| Messages (metadata) | GET /organizations/{id}/messages?from=&to=&sender=&recipient=&action=&finding= · GET /messages/{id} · POST /messages/{id}/revoke · POST /messages/{id}/resend-notification | Content never returned here |
| Holds (quarantine) | GET /organizations/{id}/holds · POST /holds/{id}/release · POST /holds/{id}/reject | Reason required; logged |
| Archive | POST /organizations/{id}/archive/search · GET /archive/messages/{id} (scope read:archive) · POST /archive/exports · GET /archive/exports/{id} (status, download URL, manifest) | Exports asynchronous; signed URLs valid 24 h |
| Legal holds | GET/POST /organizations/{id}/legal-holds · POST /legal-holds/{id}/release | Custodian, matter query, date range |
| Audit log | GET /organizations/{id}/audit?from=&to=&actor=&action= | Cursor pagination; up to 6 years |
| Reports | GET /organizations/{id}/reports/compliance?period= · GET /reports/dmarc · GET /reports/deliverability · POST /reports/evidence-pack (regulator type) | PDF and JSON |
| Billing | GET /organizations/{id}/subscription · PATCH (seats, add-ons) · GET /invoices | Partners: bill-through statements |
| Status | GET /status | Public; no auth |
Webhooks
Register endpoints in Console → Security → Webhooks or via POST /organizations/{id}/webhooks. Payloads are JSON, signed with HMAC-SHA256 in X-PXC-Signature (timestamped; replay window 5 minutes), retried with exponential backoff for 24 hours.
| Event | When |
|---|---|
message.scanned | Policy decision made (metadata, findings, action) |
message.delivered / message.locked / message.opened / message.bounced | Delivery lifecycle |
message.held / hold.released / hold.rejected | Quarantine |
policy.updated | With version and actor |
user.created / user.removed / user.mfa_reset / device.wiped | Identity and devices |
dns.changed / connection.failed / reputation.warning / reputation.paused | Health |
legal_hold.created / legal_hold.released / export.completed | Archive |
agreement.signed / subscription.updated / invoice.paid / invoice.failed | Account |
Rate limits and pagination
600 requests per minute per key (burst 100); archive search 60 per minute; exports 10 concurrent. Responses include X-RateLimit-Remaining. Lists use cursor pagination (?cursor=&limit=, max 200).
Errors
Standard HTTP codes with a JSON body: {"error":{"code":"policy.invalid","message":"…","field":"rules[3].action","request_id":"…"}}. Codes are stable and documented.
Data handling
API traffic is logged like console traffic. Message content is only available through read:archive on Hosted Pro with dual approval, and such reads appear in the organization’s access log. Webhook payloads never contain content.
SDKs and tools
OpenAPI 3.1 specification published at GA; TypeScript and Python SDKs; a Terraform provider for partners who provision many organizations; Postman collection.
Example — provision a client (partner)
POST /v1/organizations
{ "name": "Lakeside Family Dental", "profile": "hipaa", "plan": "gateway",
"domains": ["lakesidedental.com"], "owner_email": "[email protected]",
"security_officer": {"name": "Jordan Reyes", "email": "[email protected]"} }
201 Created
{ "id": "org_7f3a…", "status": "pending_agreement",
"agreements": [{"type": "baa", "sign_url": "https://sign.pxcmail.com/…"}],
"next": "Sign the BAA, then GET /domains/{id}/dns for records." }
Building on PXCMail?
Partners get API access, a sandbox organization and an engineer to talk to.
Partner program