Inbound addresses Live
Inbound addresses are the email addresses that, when emailed, become tickets in your workspace. Use generated forwarding addresses, a claimed workspace subdomain, or a reply identity on your sending domain. Receiving and sending are separate configurations.
These are authenticated dashboard endpoints. Read access requires an agent session; creation, updates, verification and archival require administrator access. A product API key is not an agent session.
Address kinds
| Kind | Example | Setup |
|---|---|---|
auto | [email protected] | Server-generated forwarding destination. Use the exact returned address. |
subdomain | [email protected] | Pick any local-part; we route on the workspace subdomain. |
custom_domain | [email protected] | Starts pending verification; inspect the returned CNAME target. |
apex | [email protected] | Reply identity linked by sendingDomainId. Receiving uses forwarding; outbound replies also require the linked sending domain to be sendable. |
List addresses
Returns { addresses: [...] }. Defaults to active addresses. Use status=all, status=archived or status=pending_verification to inspect the other states.
Code samples
curl 'https://app.message.com/api/v1/inbound-addresses' \
-H 'Authorization: Bearer YOUR_WORKSPACE_JWT'const res = await fetch('https://app.message.com/api/v1/inbound-addresses', {
headers: { Authorization: 'Bearer ' + token }
});
const { addresses } = await res.json();import requests
r = requests.get(
"https://app.message.com/api/v1/inbound-addresses",
headers={"Authorization": f"Bearer {token}"},
)
addresses = r.json()["addresses"]require "net/http"
require "json"
uri = URI("https://app.message.com/api/v1/inbound-addresses")
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{token}"
http.request(req)
end
addresses = JSON.parse(res.body)["addresses"]<?php
$ctx = stream_context_create([
"http" => ["method" => "GET", "header" => "Authorization: Bearer $token"]
]);
$addresses = json_decode(file_get_contents("https://app.message.com/api/v1/inbound-addresses", false, $ctx), true)["addresses"];Create an address
| Field | Type | Description |
|---|---|---|
| kindrequired | enum | One of auto, subdomain, custom_domain, apex. |
| localPartoptional | string | Subdomain only. The part before the @ sign. 1 to 64 chars. |
| addressoptional | string | Full address for custom_domain or apex. Apex must match the linked sending domain. |
| sendingDomainIdoptional | uuid | Required for apex. A sending domain owned by this workspace. |
| displayNameoptional | string | Optional display name, up to 200 characters. |
| departmentIdoptional | uuid | Route inbound mail at this address to this department. |
{
"kind": "subdomain",
"localPart": "support",
"departmentId": "uuid"
}Returns HTTP 201 with an address object:
{
"id": "uuid",
"kind": "subdomain",
"address": "[email protected]",
"departmentId": "uuid",
"status": "active",
"cnameVerified": false,
"sendingDomainId": null,
"displayName": "Support",
"createdAt": "2026-05-13T15:30:00Z"
}Update routing
Update departmentId, displayName or status. The address field is editable only for an apex identity and must remain on its linked sending domain. There is no PATCH localPart operation. Returns { address: ... }.
Delete an address
Archives the address and returns HTTP 204. Existing ticket history is retained. Archiving the last active auto address is blocked with cannot_archive_last_auto_address.
Verify a custom-domain route
POST /api/v1/inbound-addresses/:id/verify checks the stored CNAME target for a custom_domain address. Inspect ok and the returned address status: HTTP 200 alone does not mean DNS verified. Other address kinds return verify_only_supported_for_custom_domain.
Claim a workspace subdomain
POST /api/v1/me/workspace/subdomain accepts a slug. Check availability first with GET /api/v1/me/workspace/subdomain/available?slug=acme. Reserved or used slugs are rejected. Changing or removing a subdomain with active subdomain addresses is blocked to avoid losing incoming mail.
Sending a test email
Send a test to the customer-facing email address, then confirm the ticket appears in the intended department and a reply reaches the sender. If it does not arrive, check the forwarding rule, active destination, provider delivery logs and the selected department. Sending-domain verification alone does not configure inbound forwarding.
If you forward from Gmail or Microsoft 365, see the tutorials: Gmail forwarding and Microsoft 365 forwarding.
Errors
| Code | When |
|---|---|
400 invalid_body | Payload validation failed. |
409 address_taken | An address with this local-part / address already exists. |
400 invalid_sending_domain | The apex identity references a sending domain outside this workspace or a missing domain. |
Common pitfalls
- Using a free email provider for the local-part on a custom domain. Forwarding from Gmail to message.com works; using a Gmail address as your inbound address does not. You need a domain you control.
- Forgetting SPF / DKIM / DMARC. Use the exact records returned by the sending-domain workflow. Keep inbound forwarding separate and preserve your existing mailbox provider’s MX records.
- Routing to a deleted department. Creation and updates reject department IDs that are deleted or outside the workspace. Choose an active department.