How-to guide

Send an email

Send an email from your workspace's mailbox and keep replies in one thread.

What you'll build

A request that emails a person from your mailbox, with a subject, and replies that stay in the same thread.

Prerequisites

  • A secret API key with the messages:send scope. See Authentication and API keys.
  • A mailbox in your workspace. It is your sender on email. Without one, a send is refused with 409 no_sender.
  • curl, Node.js 18 or later with @voicelayer/api, or Python 3.9 or later with voicelayer.

Step 1: Send a new email

POST /v1/messages with channel: "email", the recipient's address in to, and a subject. The subject is only for a new email; other channels refuse it with 400 invalid_request. With a test key, send to any address at test.vlayers.ai.

curl -X POST https://api.vlayers.ai/v1/messages \
  -H "Authorization: Bearer $VOICELAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "email",
    "to": "[email protected]",
    "subject": "Your booking",
    "content": {
      "type": "text",
      "text": "Your table for two is booked for 7pm. Reply to this email to change it."
    }
  }'
Response · 202
{
  "message": {
    "id": "0192f5b0-8d1f-7b62-8c3e-5f9a2b7d4e32",
    "conversationId": "0192f5b0-7c3e-7a51-9b2d-4e8f1a6c3d21",
    "channel": "sms",
    "direction": "outbound",
    "status": "queued",
    "text": "Your table for two is booked for 7pm.",
    "media": [],
    "from": "+14155550100",
    "to": "+15550123",
    "bindingId": null,
    "metadata": {},
    "error": null,
    "createdAt": "2026-10-20T15:04:05.000Z",
    "parts": [
      {
        "id": "0192f5b0-8d1f-7b62-8c3e-5f9a2b7d4e32",
        "status": "queued"
      }
    ]
  }
}

With several mailboxes, name one in from: { "mailboxId": "<mailbox address>" }.

Step 2: Reply in the thread

When the person answers, their email arrives as a message.received event in the same conversation. Reply with POST /v1/conversations/{id}/messages: the reply keeps the thread's subject, so the person's mail app shows one thread.

export CONVERSATION_ID=<the conversation's id>
curl -X POST "https://api.vlayers.ai/v1/conversations/$CONVERSATION_ID/messages" \
  -H "Authorization: Bearer $VOICELAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": {
      "type": "text",
      "text": "Yes, we have a table at 7pm. Shall I book it?"
    }
  }'

Test it

With a test key, email any address at test.vlayers.ai, such as [email protected]. Nothing is sent and it costs nothing. To test a reply, simulate an incoming email first; it arrives on your mailbox, or on your free test sender if you have none:

curl -X POST https://api.vlayers.ai/v1/test/inbound \
  -H "Authorization: Bearer $VOICELAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "email",
    "from": "[email protected]",
    "text": "Can I move my booking to Friday?"
  }'

Save the returned conversationId as CONVERSATION_ID and reply with Step 2. See Test mode.

Common errors

ErrorStatusHow to fix
no_sender409Connect a sender for the channel in the dashboard (for email, create a mailbox), or name one in from.
sender_ambiguous409Name one of details.senders in from.
invalid_request400Read message and details.issues (the validation issues, by path), fix the request and send it again.
test_address_required422Use a reserved test address, or a live key to reach a real person.
rate_limited429Wait for retry-after, then retry (with the same Idempotency-Key for a send).

Next steps

On this page