Mail integration
Authentication and ownership
Base URL: https://cloud-api.adaptgroup.pro. Every request uses the Cloud integration key in X-Api-Key and its numeric api_key_id: in the query for GET/DELETE, in JSON for other methods. Send JSON with Content-Type: application/json.
An account represents your customer. api_user_id is your stable customer identifier, up to 255 characters. An account can own domains and mailboxes. account_id, domain_id, mailbox_id and key_id identify resources; operation_id is a UUID. Resources must belong to the authenticated integration.
Cloud integration keys manage services and payments. Mail API keys let your application work with messages, folders and attachments through the mail API. They are integration credentials, so keep them on your backend rather than distributing them to individual customers. Login at adapt-mail.com uses an account login and password. Account passwords and mailbox passwords are separate.
Sign in without a password
Call POST /mail/accounts/{account_id}/login-link from your backend with api_key_id and optional locale (default en). Omit mailbox_id or pass null to open the account; provide it to open only that mailbox. Languages: en, ru, fr, es, de, zh-cn, ko, tr, hi, pt-br.
HTTP 201 returns data.login_url, expires_in: 300, expires_at, account_id and mailbox_id. Open the complete URL, preserving #token=.... The link is single-use and valid for five minutes; do not log or cache it. Check that your signed-in customer owns the requested account or mailbox before issuing a link. Keep the Cloud API key on your backend.
For a new tab, open a blank tab directly on the click, then navigate it to login_url after the response. Passwords and existing browser logins remain unchanged. Access is checked again at sign-in. If the link expires or has already been used, create a new one. The mail interface exchanges the token itself.
Create an account and connect a domain
- Call
POST /mail/accountswithapi_user_idandname. Account creation is free. Save the generatedloginandpassword; subsequent reads do not return the password. Repeating creation with the same customer ID and name returns the existing account. Use password reset to obtain a new password. - Call
POST /mail/accounts/{account_id}/domainswithname: "example.com". Pass only the domain name, without a URL scheme or path. Mailboxes use your connected domain;adapt-mail.comis the mail interface, not a domain supplied for customer addresses. - Read DNS records and publish them at your DNS provider.
- Call verify. It checks the ownership TXT and activates the domain. The response also contains the newly generated DKIM TXT: publish that record too.
- Read DNS again. When
status="active"and every record hasmatches=true, DNS setup is complete. Continue with mailbox purchase.
GET /mail/domains lists all owned domains without selecting a customer. GET /mail/accounts/{account_id}/domains lists domains available to one account.
Reading DNS records
| Field | Meaning |
|---|---|
type | DNS record type, such as TXT or MX. |
name | Full DNS record name. If the provider appends your domain automatically, enter only the relative name; use @ for the root when required by the provider. |
value | Expected content. Copy the complete value, including a long DKIM public key. |
observed | Values found by the check. |
matches | Whether an observed value matches the expected value. |
error | dns_unavailable when this record could not be checked. |
| Record | Name for example.com | Value / purpose |
|---|---|---|
| Ownership TXT | _adapt-mail.example.com | Exact verification value from the API. |
| MX | example.com | For 10 mx1.adapt-mail.com, set priority: 10 and mail server: mx1.adapt-mail.com in separate provider fields. |
| SPF TXT | example.com | Complete SPF value returned by the API. |
| DMARC TXT | _dmarc.example.com | Complete DMARC value returned by the API. |
| DKIM TXT | dkim._domainkey.example.com | Complete generated DKIM value returned after verification. |
status=active confirms domain activation, not that MX, SPF, DMARC and DKIM all match. Use records[].matches for that check. If records do not match, check the name and value and allow DNS changes to propagate before checking again.
Keep the records returned by the API while using the domain for mail. MX directs incoming mail; SPF, DKIM and DMARC support sender verification. The ownership TXT is used when the domain is verified again. Do not remove them as a setup cleanup step.
Purchase and payment
Read GET /mail/plans, choose an active code, and use its monthly_price_usd. Prices are final USD prices; the integration markup is not added. storage_shared=true means messages, attachments and files share one quota. mail_quota_mb and file_quota_mb are equal and describe the same capacity in MiB; do not add them. There is no separate purchase quote.
curl 'https://cloud-api.adaptgroup.pro/mail/mailboxes' \
-H 'X-Api-Key: YOUR_CLOUD_API_KEY' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: mail-customer-42-order-001' \
--data '{
"api_key_id": 1,
"account_id": 12,
"domain_id": 8,
"local_part": "team",
"name": "Team",
"password": "ExamplePassword42!",
"plan_code": "mail-10",
"auto_renew": false,
"expected_amount_usd": "1.0000"
}'
This creates [email protected]. Replace the IDs, domain, password and price with your actual values. api_user_id comes from the selected account and is not a purchase field.
Purchase, renewal, storage upgrade and deletion return HTTP 202 with an order. Read GET /orders/{order_id} until the outcome is known. A completed purchase supplies mailbox_id, mail_operation_id and paid_until. Then read mailbox details. Provisioning acceptance does not mean that the mailbox is ready. Billing starts after successful provisioning, for one calendar month.
The integration balance is charged when an order is accepted. Insufficient funds return 409 insufficient_balance, unless negative balance is enabled for your integration. A confirmed failed purchase is refunded after cleanup; check the order status and error_code. review means the result still requires resolution; do not create a replacement paid order just to retry it.
Idempotency-Key is required for purchase, renewal, upgrade, deletion and mailbox settings. It must contain 8–128 printable ASCII characters without spaces. Use one key per command. After a timeout, repeat the same request with the same key. An order key reused with different parameters returns 409 idempotency_conflict.
expected_amount_usd is optional and uses four decimal places. Purchase and renewal compare it to the exact amount. For an upgrade it sets the maximum accepted extra charge, allowing the quote to decrease as time passes. A changed or higher price returns 409 price_changed without payment.
Shared storage
The base plan provides 10 GiB total for mail and files. Storage upgrades increase this single quota; files are not a separate paid service.
Mailbox details and lists return storage_shared=true. Display total usage as used_bytes / (quota_mb × 1048576). used_bytes already includes files, MIME encoding and headers. file_quota_bytes equals quota_mb × 1048576; file_used_bytes is the original size of separate files before MIME encoding and is an analytical value, not additional usage. Do not add either file field to its corresponding total.
Renewal, upgrades and deletion
- Renewal: quote, then renew. Each renewal buys one calendar month at the current plan price, starting at the later of the paid-through date and now. Calendar months retain the time of day in UTC and use the last available day in shorter months.
- Storage upgrade: quote, then upgrade. Only a larger plan is allowed. The extra charge covers the remaining fraction of every paid calendar month, including months paid in advance. The paid-through date stays unchanged. Quotes do not reserve funds or create orders.
- Auto-renewal: disabled by default; set it during purchase or through auto-renew. The service attempts one-month renewal from the integration balance one hour before expiry and, if still unpaid, one hour before deletion.
- Expiry: access is suspended when payment expires. Renewal remains possible for 24 hours after expiry, until deletion starts.
delete_aftergives the deletion deadline. Once deletion begins, renewal is unavailable. - Manual deletion:
DELETE /mail/mailboxes/{mailbox_id}creates a zero-price order and deletes the mailbox, messages and files. The unused term is not refunded.
Mail payments appear in transactions as mail_purchase, mail_renewal and mail_upgrade; returned funds use refund. Orders additionally include mail_delete. mailbox_id links an order to the mailbox, and mail_operation_id links it to the mail operation. For completed mail orders, paid_until is returned when the operation has a confirmed term.
Settings and operations
PATCH mailbox settings changes the display name, mailbox password or signature. Omitted fields and null leave values unchanged; an empty signature clears it. HTTP 200 returns a queued operation. Read the operation by its UUID and account ID; succeeded confirms completion.
Access settings block or enable a mailbox without pausing the paid term. Renewal does not remove a manual block. Account reassignment moves a mailbox within your integration, retaining its address, password, data and paid term while updating api_user_id.
Operation states are queued, running, succeeded, failed, uncertain and cancelled. uncertain means the outcome has not been confirmed. error is a public error code or null; result contains public result fields when available. Retry is available for eligible failed settings and paid storage upgrades in review, without another payment. Sending operations cannot be retried through that route.
Sending limits and usage
Mailbox list and details include limits and usage in one response:
| Limit / usage fields | Window |
|---|---|
outbound_daily_recipient_limit, outbound_daily_recipients_used, outbound_daily_recipients_remaining | Recipients in the last 24 hours. |
outbound_messages_per_minute, outbound_minute_messages_used, outbound_minute_messages_remaining | Messages in the last 60 seconds. |
outbound_recipients_per_message | Total recipients in To/Cc/Bcc of one message. |
The daily allowance is 1000 recipients, or 5000 when outbound_high_limit=true. The other limits are 30 messages per minute and 50 recipients per message. Limits are independent of storage size. SMTP and API share the counters. remaining is at least zero. Usage measures accepted sending attempts, not confirmed delivery; an accepted operation can still fail at sending time. Unavailable usage returns 503, never fabricated zeroes.
The auto-renewal settings response also includes current usage. Access and reassignment responses contain limit values but not usage counters; read mailbox details for updated usage.
Mail API keys
Create a named key, list keys without secrets and view an active key when needed. Creation and viewing return key; secret-bearing responses are not cached. To remove a key, first revoke it, then call the same DELETE route with permanent=true. An active key cannot be permanently deleted.
Errors and webhooks
HTTP 401 means the integration key/ID is invalid or the integration is inactive; 403 means access is denied; 404 means the resource is not available to this integration; 422 means invalid request fields or parameters. A structured error has detail.code and detail.message; some validation and state errors use other detail shapes, so also handle the HTTP status.
| Code | Action |
|---|---|
insufficient_balance | Top up the integration or use its approved negative-balance allowance. |
price_changed | Read the current catalog or quote and confirm the new amount. |
idempotency_conflict | Use the original parameters for a retry, or a new key for a different command. |
mail_busy, mail_domain_busy | Wait for the current operation, then repeat. |
mail_conflict | Re-read the resource state before changing it. |
mail_plan_unavailable | Select an active plan from the catalog. |
mail_request_rejected | Correct the request parameters. |
mail_access_denied, mail_not_found | Check ownership, IDs and access. |
mail_domain_shared | A shared domain cannot be deleted. |
mail_domain_has_mailboxes | Delete its mailboxes and wait for completion. |
mail_domain_deleting, mail_domain_delete_failed | Repeat deletion to confirm completion. |
mail_key_active | Revoke the key before permanent deletion. |
mail_key_not_recoverable | Create a new key. |
mail_unavailable | Retry reading when the service is available. |
mail_operation_unconfirmed | Check the original operation/resource; do not assume the command failed. |
Order errors mail_rejected and mail_creation_failed indicate a rejected/failed order whose payment was returned; mail_unconfirmed requires checking the original operation. Sending errors and all mailbox lifecycle events are described in Webhooks. No password, API key or message body is included in partner webhooks.