Getting started
Quickstart
Create an API key, create an inbox, send a message, and read the reply, in about five minutes.
1. Create an account and an API key
- Sign in at goshenemail.com/app. Sign-in is passwordless: enter your email and use the magic link or the six-digit code.
- Open API keys in the sidebar and choose New key.
- Give the key a name, pick its scopes (for this walkthrough, all five), and choose an expiration. Keys default to 30 days.
- Copy the key. It is shown once. Goshen Email stores only its SHA-256 hash.
Account keys start with bze_. Put the key in your environment; never paste it into prompts, code, or browser storage.
export GOSHENEMAIL_API_KEY="bze_..."
export GOSHENEMAIL_BASE_URL="https://api.goshenemail.com"
2. Create an inbox
curl "$GOSHENEMAIL_BASE_URL/v1/inboxes" \
-H "Authorization: Bearer $GOSHENEMAIL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"username":"research","displayName":"Research agent","group":"agents"}'
{
"inboxId": "research@agents.goshenemail.com",
"address": "research@agents.goshenemail.com",
"displayName": "Research agent",
"group": "agents",
"createdAt": "2026-09-20T18:04:11.000Z",
"deliveryStatus": "ready"
}
inboxId is the inbox's canonical email address. Use the returned value in every later call. If the response is lost, call the same request again with the same username; a retry returns the same inbox instead of creating a second one.
If deliveryStatus is pending, delivery routing did not finish. The address stays reserved; call Finish inbox setup to retry.
3. Send a message
Every send needs an idempotencyKey that you generate and keep. Retrying with the same key and the same contents never sends twice.
curl "$GOSHENEMAIL_BASE_URL/v1/inboxes/research%40agents.goshenemail.com/messages/send" \
-H "Authorization: Bearer $GOSHENEMAIL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": ["vendor@example.net"],
"subject": "Quote request",
"text": "Hello, could you send the current quote for 200 units?",
"idempotencyKey": "2f7c1c1e-6d1a-4a3b-9b0e-0c9b3f5c8a11"
}'
{ "messageId": "<20260920180512.7f3a@agents.goshenemail.com>", "threadId": "0b8d0e7f-3444-4bb7-a250-c2793dd5944d" }
Path segments are URL encoded, so @ becomes %40. The CLI does this for you.
4. Read the reply
When the vendor answers, the reply lands in the same inbox with the received and unread labels and joins the same thread.
curl "$GOSHENEMAIL_BASE_URL/v1/inboxes/research%40agents.goshenemail.com/messages?labels=received&labels=unread" \
-H "Authorization: Bearer $GOSHENEMAIL_API_KEY"
To read the whole conversation in order:
curl "$GOSHENEMAIL_BASE_URL/v1/inboxes/research%40agents.goshenemail.com/threads/0b8d0e7f-3444-4bb7-a250-c2793dd5944d?includeBodies=true" \
-H "Authorization: Bearer $GOSHENEMAIL_API_KEY"
5. Reply in the thread
curl "$GOSHENEMAIL_BASE_URL/v1/inboxes/research%40agents.goshenemail.com/messages/<message-id>/reply" \
-H "Authorization: Bearer $GOSHENEMAIL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Thanks. Does the quote include shipping?","idempotencyKey":"9d5a0f0e-1b7c-4c1e-8f3a-6c2d1e0b9a77"}'
reply addresses the original sender and keeps the thread. Set replyAll: true to include everyone on the original message, or pass to, cc, and bcc to choose recipients yourself.
Next
- MCP server gives an agent the inbox as tools instead of HTTP calls.
- Sending mail explains idempotency, retries, attachments, and limits.
- Labels covers the system labels (
received,sent,unread,trash,quarantined) and your own. - Quarantine explains why some incoming mail waits for a person.