Using the Admin API
The Admin API is a JSON-over-HTTP RPC API served by the admin-api Lambda. Every operation is a POST request with a JSON body; there are no GET, PUT, or DELETE routes.
Endpoint URL
Section titled “Endpoint URL”The Admin API is served at api.<domainName>. The Mailbox CDK construct provisions the ACM certificate and Route 53 record automatically.
If the optional prefix property is set, a label is inserted between the service name and the base domain:
| CDK props | Admin API endpoint |
|---|---|
domainName: "example.com" | https://api.example.com |
domainName: "example.com", prefix: "mailbox" | https://api.mailbox.example.com |
Authentication
Section titled “Authentication”The Admin API requires a Bearer JWT issued by the Cognito User Pool that was passed to the Mailbox construct. The token must carry the adminApi audience and the ADMIN permission scope.
Machine-to-machine (headless) access
Section titled “Machine-to-machine (headless) access”Use the OAuth 2.0 client_credentials flow. The CDK stack provisions a dedicated headless client whose credentials are available as CloudFormation outputs (AdminHeadlessClientId and AdminHeadlessClientSecret).
# 1 — Obtain a token from Cognito# The exact scope string depends on your IDP plugin configuration.# Check the CloudFormation outputs or ask your administrator for the configured scope.TOKEN=$(curl -s -X POST \ "https://<cognito-domain>.auth.<region>.amazoncognito.com/oauth2/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials" \ -d "client_id=<AdminHeadlessClientId>" \ -d "client_secret=<AdminHeadlessClientSecret>" \ -d "scope=<admin-scope>" \ | jq -r '.access_token')
# 2 — Use the token in every Admin API callcurl -s -X POST "https://api.mail.example.com/domains/ListDomains" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{}'User-context access
Section titled “User-context access”Admin console UIs use the authorization_code flow. A short-lived access token is obtained via the Cognito hosted UI and sent in the same Authorization: Bearer header.
Request format
Section titled “Request format”Every method call follows the same pattern:
POST /<service>/<MethodName>Authorization: Bearer <token>Content-Type: application/json
{ ...request fields... }The service path and method name map directly to the protobuf service definitions in mailbox-idl/admin-api/proto/. For example, DomainsService.ListDomains is called at:
POST /domains/ListDomainsResponse format
Section titled “Response format”Successful responses return HTTP 200 with a JSON body containing the response fields defined in the IDL. There is no envelope wrapper — the response is the message directly.
Errors return a non-2xx status code with a JSON body:
{ "code": "not_found", "message": "Domain 'example.com' does not exist"}Common status codes:
| Code | Meaning |
|---|---|
200 | Success |
400 | Validation error — check the message field |
401 | Missing or invalid token |
403 | Token lacks the required permission scope |
404 | Requested resource not found |
409 | Conflict (e.g. DNS record already exists) |
500 | Internal error |
Example: verifying the deployment
Section titled “Example: verifying the deployment”The /status/Ping endpoint requires no specific scope and is useful for smoke-testing:
curl -s -X POST "https://api.mail.example.com/status/Ping" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{}'# → {}Example: provisioning a domain
Section titled “Example: provisioning a domain”# 1 — Register a domaincurl -s -X POST "https://api.mail.example.com/domains/CreateDomain" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"domain": "acme.com"}' | jq .
# 2 — List DNS records the domain requirescurl -s -X POST "https://api.mail.example.com/domains/GetDomainVerification" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"domain_id": "<id-from-step-1>"}' | jq .
# 3 — Once DNS is in place, verifycurl -s -X POST "https://api.mail.example.com/domains/VerifyDomain" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"domain_id": "<id-from-step-1>"}' | jq .Example: creating a user with a mailbox
Section titled “Example: creating a user with a mailbox”# 1 — Create the userUSER=$(curl -s -X POST "https://api.mail.example.com/users/CreateUser" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "email": "alice@acme.com", "display_name": "Alice" }' | jq .)echo $USER
# 2 — Add a mail alias so she can receive emailcurl -s -X POST "https://api.mail.example.com/aliases/CreateAlias" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "account_id": "<account_id from USER>", "local_part": "alice", "domain_id": "<domain_id for acme.com>", "is_active": true }' | jq .