Your first conversation
Create an inbox, send an email, and read a reply.
This guide starts after access approval. Create an agent key in your dashboard. You also need a terminal with curl and jq, and an email address you control for the other side of the conversation.
Your key needs mailbox:manage, mailbox:send, mailbox:read, and delivery:read. A key with * includes these. If it is restricted to specific inboxes or reply-only sending, check your access before continuing.
1. Check your access
Store your key in your local environment. Replace YOUR_API_KEY with the key you created in the dashboard. Keep the key out of source control and browser code.
export MAILACTOR_API_URL="https://api.mailactor.com"
export MAILACTOR_API_KEY="YOUR_API_KEY"
curl --fail-with-body --silent --show-error \
"$MAILACTOR_API_URL/v1/me" \
-H "x-api-key: $MAILACTOR_API_KEY"Check organization.status, apiKey.scopes, and managedStarter.remaining. The response also includes your key restrictions and the current platform limits.
2. Create an inbox
You already have a starter inbox after approval. To use it, list your inboxes, save its exact ID, and continue at step 3. The example below creates an additional managed inbox; no DNS setup is needed.
INBOX=$(curl --fail-with-body --silent --show-error \
"$MAILACTOR_API_URL/v1/inboxes" \
-H "x-api-key: $MAILACTOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"localPart":"research-agent","displayName":"Research Agent"}')
export INBOX_ID=$(printf '%s' "$INBOX" | jq -er '.id')
printf '%s' "$INBOX" | jq '{id, address, status}'Save the returned id and exact address. If you get 409, list your inboxes before retrying: that name may already be in use. Inbox creation does not use an idempotency key. If its response is lost, page the complete inventory and match your requested localPart plus domainKind: "managed"; save the exact returned address. A conflict alone does not prove that your organization owns it. See creation recovery.
3. Send your first email
Set RECIPIENT to an email address you control. Keep SEND_KEY for retries of this exact message; generate a fresh key for a new email.
export RECIPIENT="you@example.com"
export SEND_KEY="first-send-$(uuidgen)"
PAYLOAD=$(jq -n --arg email "$RECIPIENT" \
'{to:[{email:$email}],subject:"Hello from Mailactor",text:"My agent has an inbox. Reply to start a conversation!"}')
SENT=$(curl --fail-with-body --silent --show-error \
"$MAILACTOR_API_URL/v1/inboxes/$INBOX_ID/messages" \
-H "x-api-key: $MAILACTOR_API_KEY" \
-H "idempotency-key: $SEND_KEY" \
-H "Content-Type: application/json" \
-d "$PAYLOAD")
export THREAD_ID=$(printf '%s' "$SENT" | jq -er '.message.threadId')
export SUBMISSION_ID=$(printf '%s' "$SENT" | jq -er '.submission.id')
printf '%s' "$SENT" | jq '{messageId: .message.id, threadId: .message.threadId, submissionId: .submission.id}'The command prints selected identifiers from the response (illustrative values):
{
"messageId": "msg_1123456789abcdef01234567",
"threadId": "thr_0123456789abcdef01234567",
"submissionId": "00000000-0000-4000-8000-000000000001"
}The full HTTP body is {message, submission, replayed}; see the complete send response. A successful send returns 202 Accepted. It means the message and delivery submission are stored; delivery happens asynchronously.
4. Confirm delivery
Wait one second before checking the submission. For subsequent checks, wait 2 seconds, then 4 seconds, then at most 5 seconds between checks. Set a deadline for your workflow.
curl --fail-with-body --silent --show-error \
"$MAILACTOR_API_URL/v1/submissions/$SUBMISSION_ID" \
-H "x-api-key: $MAILACTOR_API_KEY" | jq '{status, recipients}'Continue while the status is pending, queued, or deferred. For this single-recipient example, delivered confirms the recipient's server accepted the message. Other outcomes need attention; see delivery status. If the deadline expires, preserve the submission ID and report its actual state.
5. Receive a reply
Open the message in your other mailbox and reply normally. Mailactor receives it at your inbox address and adds it to the conversation.
curl --fail-with-body --silent --show-error \
"$MAILACTOR_API_URL/v1/threads/$THREAD_ID?limit=20" \
-H "x-api-key: $MAILACTOR_API_KEY" | jq '{id, messages, nextCursor}'Look for a message with direction: "inbound". Arrival and parsing are asynchronous: use the same bounded polling schedule if it is not visible yet. Follow nextCursor when present. Do not mistake the original outbound message for an incoming reply.
You now have a two-way conversation. Next, reply through the API or register a webhook to receive notifications automatically.