Addresses API
Complete reference for all address endpoints -- create, retrieve, list, delete, and email access.
All endpoints use the base URL https://api.oneshotemail.com/v1 and require Authorization: Bearer <api_key> unless noted otherwise.
Create an address
POST /addresses
Creates a new one-shot email address. The address can be in receive mode (wait for an incoming email) or send mode (send a single outgoing email).
Receive mode
Create an address that waits for one inbound email:
curl -X POST https://api.oneshotemail.com/v1/addresses \
-H "Authorization: Bearer osm_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"ttl_seconds": 3600,
"label": "signup-test",
"mode": "receive"
}'
Request body:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
ttl_seconds | int | No | 3600 | Seconds until the address auto-expires. |
label | string | No | null | Label for filtering and bulk cleanup. |
mode | string | No | "receive" | "receive" or "send". |
Response: 201 Created
{
"id": "abc123xyz789def456",
"address": "abc123xyz789def456@in.oneshotemail.com",
"mode": "receive",
"status": "waiting",
"expires_at": "2026-03-08T12:00:00Z",
"label": "signup-test"
}
Send mode
Create an address and immediately send one email from it:
curl -X POST https://api.oneshotemail.com/v1/addresses \
-H "Authorization: Bearer osm_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"mode": "send",
"ttl_seconds": 300,
"label": "invoice-test",
"send": {
"to": "intake@myapp.com",
"subject": "Test invoice submission",
"text_body": "Please process this invoice.",
"html_body": "<html><body><p>Please process this invoice.</p></body></html>",
"attachments": [
{
"filename": "invoice.pdf",
"content_type": "application/pdf",
"content_base64": "JVBERi0xLjQK..."
}
]
}
}'
Send request body (nested under send):
| Field | Type | Required | Description |
|---|---|---|---|
to | string | Yes | Destination email address. |
subject | string | Yes | Email subject line. |
text_body | string | No | Plain text email body. |
html_body | string | No | HTML email body. |
attachments | array | No | List of attachment objects. |
attachments[].filename | string | Yes | Filename for the attachment. |
attachments[].content_type | string | Yes | MIME type (e.g., application/pdf). |
attachments[].content_base64 | string | Yes | Base64-encoded file content. |
Response: 201 Created
{
"id": "def456abc789xyz123",
"address": "def456abc789xyz123@out.oneshotemail.com",
"mode": "send",
"status": "sent",
"send_to": "intake@myapp.com",
"expires_at": "2026-03-08T12:05:00Z",
"label": "invoice-test"
}
Error responses
| Status | Code | Description |
|---|---|---|
| 400 | VALIDATION_ERROR | Invalid request body (bad TTL, missing fields, etc.) |
| 401 | UNAUTHORIZED | Missing or invalid API key. |
| 402 | QUOTA_EXCEEDED | Monthly allocation and credits exhausted. |
| 429 | RATE_LIMITED | Too many requests. |
Get an address
GET /addresses/{id}
Retrieve an address by ID, including its current status and email summary (if an email has been received).
curl https://api.oneshotemail.com/v1/addresses/abc123xyz789def456 \
-H "Authorization: Bearer osm_live_your_key"
Response: 200 OK (waiting — no email yet)
{
"id": "abc123xyz789def456",
"address": "abc123xyz789def456@in.oneshotemail.com",
"mode": "receive",
"status": "waiting",
"expires_at": "2026-03-08T12:00:00Z",
"label": "signup-test",
"email": null
}
Response: 200 OK (received)
{
"id": "abc123xyz789def456",
"address": "abc123xyz789def456@in.oneshotemail.com",
"mode": "receive",
"status": "received",
"expires_at": "2026-03-08T12:00:00Z",
"label": "signup-test",
"email": {
"from": "noreply@example.com",
"subject": "Verify your account",
"received_at": "2026-03-08T11:30:00Z",
"size_bytes": 15234,
"has_attachments": true,
"attachment_count": 2
}
}
Error responses
| Status | Code | Description |
|---|---|---|
| 401 | UNAUTHORIZED | Missing or invalid API key. |
| 404 | NOT_FOUND | Address does not exist. |
| 410 | EXPIRED | Address has expired and been deleted. |
Get email content
GET /addresses/{id}/email
Retrieve the full parsed email for an address. Returns the text body, HTML body, headers, and attachment metadata.
curl https://api.oneshotemail.com/v1/addresses/abc123xyz789def456/email \
-H "Authorization: Bearer osm_live_your_key"
Response: 200 OK
{
"from": "noreply@example.com",
"to": "abc123xyz789def456@in.oneshotemail.com",
"subject": "Verify your account",
"text_body": "Click the link below to verify your account:\nhttps://example.com/verify?token=abc123",
"html_body": "<html><body><p>Click <a href=\"https://example.com/verify?token=abc123\">here</a> to verify your account.</p></body></html>",
"headers": {
"Message-ID": "<abc@example.com>",
"Date": "Sat, 08 Mar 2026 11:30:00 +0000",
"DKIM-Signature": "v=1; a=rsa-sha256; d=example.com; ...",
"Received-SPF": "pass"
},
"received_at": "2026-03-08T11:30:00Z",
"size_bytes": 15234,
"attachments": [
{
"filename": "invoice.pdf",
"content_type": "application/pdf",
"size_bytes": 52400,
"download_url": "/addresses/abc123xyz789def456/email/attachments/0"
},
{
"filename": "receipt.png",
"content_type": "image/png",
"size_bytes": 8100,
"download_url": "/addresses/abc123xyz789def456/email/attachments/1"
}
]
}
Error responses
| Status | Code | Description |
|---|---|---|
| 401 | UNAUTHORIZED | Missing or invalid API key. |
| 404 | NOT_FOUND | No email has arrived yet (address is waiting). |
| 410 | EXPIRED | Address has expired. |
Download attachment
GET /addresses/{id}/email/attachments/{index}
Download a specific attachment by its zero-based index. Returns the raw binary file with correct Content-Type and Content-Disposition headers.
curl -O -J https://api.oneshotemail.com/v1/addresses/abc123xyz789def456/email/attachments/0 \
-H "Authorization: Bearer osm_live_your_key"
Response: 200 OK
Headers:
Content-Type: application/pdf
Content-Disposition: attachment; filename="invoice.pdf"
Content-Length: 52400
Body: raw binary file content.
Error responses
| Status | Code | Description |
|---|---|---|
| 404 | NOT_FOUND | No such attachment index. |
| 410 | EXPIRED | Address has expired. |
Get raw email
GET /addresses/{id}/email/raw
Retrieve the complete raw RFC 822 email source. Useful for debugging and inspecting DKIM, SPF, and DMARC headers.
curl https://api.oneshotemail.com/v1/addresses/abc123xyz789def456/email/raw \
-H "Authorization: Bearer osm_live_your_key"
Response: 200 OK (text/plain)
Return-Path: <noreply@example.com>
Received: from mail-wr1-f42.google.com ...
DKIM-Signature: v=1; a=rsa-sha256; d=example.com; ...
From: noreply@example.com
To: abc123xyz789def456@in.oneshotemail.com
Subject: Verify your account
Date: Sat, 08 Mar 2026 11:30:00 +0000
Content-Type: multipart/mixed; boundary="----=_Part_123"
------=_Part_123
Content-Type: text/plain; charset="UTF-8"
Click the link below to verify your account:
https://example.com/verify?token=abc123
------=_Part_123--
List addresses
GET /addresses
List addresses belonging to the authenticated user, with optional filtering and pagination.
curl "https://api.oneshotemail.com/v1/addresses?status=waiting&label=ci-run-abc123&limit=10" \
-H "Authorization: Bearer osm_live_your_key"
Query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
status | string | (all) | Filter: waiting, received, expired, sent. |
label | string | (all) | Filter by exact label match. |
mode | string | (all) | Filter: receive or send. |
limit | int | 20 | Max results per page (1—100). |
cursor | string | (none) | Pagination cursor from a previous response. |
Response: 200 OK
{
"items": [
{
"id": "abc123xyz789def456",
"address": "abc123xyz789def456@in.oneshotemail.com",
"mode": "receive",
"status": "waiting",
"expires_at": "2026-03-08T12:00:00Z",
"label": "ci-run-abc123",
"email": null
},
{
"id": "ghi789jkl012mno345",
"address": "ghi789jkl012mno345@in.oneshotemail.com",
"mode": "receive",
"status": "received",
"expires_at": "2026-03-08T12:00:00Z",
"label": "ci-run-abc123",
"email": {
"from": "noreply@example.com",
"subject": "Welcome!",
"received_at": "2026-03-08T11:32:00Z",
"size_bytes": 3200,
"has_attachments": false,
"attachment_count": 0
}
}
],
"next_cursor": "eyJsYXN0X2tleSI6Ii4uLiJ9"
}
To fetch the next page, include the next_cursor value:
curl "https://api.oneshotemail.com/v1/addresses?cursor=eyJsYXN0X2tleSI6Ii4uLiJ9" \
-H "Authorization: Bearer osm_live_your_key"
When next_cursor is null, there are no more results.
Delete an address
DELETE /addresses/{id}
Delete a specific address and all associated email data immediately, regardless of remaining TTL. Useful for test cleanup.
curl -X DELETE https://api.oneshotemail.com/v1/addresses/abc123xyz789def456 \
-H "Authorization: Bearer osm_live_your_key"
Response: 204 No Content
No response body.
Bulk delete by label
DELETE /addresses?label={label}
Delete all addresses matching the given label. This is the recommended cleanup method for test suites.
curl -X DELETE "https://api.oneshotemail.com/v1/addresses?label=ci-run-abc123" \
-H "Authorization: Bearer osm_live_your_key"
Response: 204 No Content
No response body. All matching addresses and their email data are permanently deleted.
Common patterns
Polling for an email
If you are not using an SDK with built-in wait_for_email(), you can poll the address endpoint:
# Create the address
ADDR=$(curl -s -X POST https://api.oneshotemail.com/v1/addresses \
-H "Authorization: Bearer $ONESHOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"ttl_seconds": 300}' | jq -r '.id')
# Poll until received
while true; do
STATUS=$(curl -s https://api.oneshotemail.com/v1/addresses/$ADDR \
-H "Authorization: Bearer $ONESHOT_API_KEY" | jq -r '.status')
if [ "$STATUS" = "received" ]; then
break
fi
sleep 2
done
# Fetch the email
curl -s https://api.oneshotemail.com/v1/addresses/$ADDR/email \
-H "Authorization: Bearer $ONESHOT_API_KEY" | jq .
However, the SDKs handle polling for you with exponential backoff. Use wait_for_email() whenever possible.