/curl Temp Email API
Create disposable inboxes, poll for verification emails, and extract OTP codes straight from the shell — pure curl + jq, copy-paste ready for scripts and CI.
Sometimes you just want a temporary inbox from the command line — to smoke-test a signup, script an integration check, or wire a step into CI without pulling in a language runtime. curl plus jq is all you need: one request creates a disposable inbox, a short loop polls for the email, and jq pulls the OTP out of the body. Every command below hits the real OpenInbox API.
How the flow works
- Create a disposable inbox: curl -X POST /api/inbox (no auth) → JSON with id and email.
- Trigger your app so it emails that address.
- Poll GET /api/inbound/api/emails?inboxEmail=<email> with -H "X-API-KEY: ..." until jq sees an email.
- Pipe textBody through grep/jq to extract the 4–8 digit code.
Setup
curl ships with macOS and Linux. Install jq for JSON parsing (brew install jq, or apt-get install jq). Polling is a premium endpoint, so export your key once per shell.
# jq is the only extra tool you need
brew install jq # macOS
sudo apt-get install jq # Debian/Ubuntu
export OPENINBOX_API_KEY="your-premium-api-key"Create an inbox
Creating an inbox takes no authentication. The response is a JSON object — pull the address out with jq.
curl -s -X POST https://api.openinbox.io/api/inbox
# Response:
# {
# "id": "abc123",
# "email": "[email protected]",
# "expiresAt": "2026-04-07T12:00:00Z",
# "createdAt": "2026-04-07T11:00:00Z",
# "isActive": true
# }
# Capture just the address:
EMAIL=$(curl -s -X POST https://api.openinbox.io/api/inbox | jq -r '.email')
echo "$EMAIL"Poll for the email and extract the OTP
The poll endpoint returns { "emails": [ ... ], "total": N }, so jq reads the list under .emails. This full script creates an inbox, waits up to ~30 seconds, and prints the first 4–8 digit code found in the body.
#!/usr/bin/env bash
set -euo pipefail
API="https://api.openinbox.io/api"
: "${OPENINBOX_API_KEY:?Set OPENINBOX_API_KEY to your premium key}"
# 1. Create a disposable inbox (no auth)
EMAIL=$(curl -s -X POST "$API/inbox" | jq -r '.email')
echo "Inbox: $EMAIL"
# 2. (Trigger your app so it emails $EMAIL …)
# 3. Poll for up to ~30s
for _ in $(seq 1 15); do
EMAILS=$(curl -s "$API/inbound/api/emails?inboxEmail=$EMAIL" \
-H "X-API-KEY: $OPENINBOX_API_KEY")
if [ "$(echo "$EMAILS" | jq '.emails | length')" -gt 0 ]; then
# 4. Extract a 4–8 digit OTP from the body
OTP=$(echo "$EMAILS" | jq -r '.emails[0].textBody' | grep -oE '[0-9]{4,8}' | head -1)
echo "OTP: $OTP"
exit 0
fi
sleep 2
done
echo "No email arrived in time" >&2
exit 1One-liner
Once an inbox has received mail, grab the latest code in a single pipeline:
curl -s "https://api.openinbox.io/api/inbound/api/emails?inboxEmail=$EMAIL" \
-H "X-API-KEY: $OPENINBOX_API_KEY" \
| jq -r '.emails[0].textBody' | grep -oE '[0-9]{4,8}' | head -1Inspect the full message
The poll response carries everything about each email, so jq can read the subject, sender, HTML body, or read-state without a second request — useful for asserting who sent the email or that the right template rendered. For busy inboxes, page through results with page and limit.
# Sender and subject of the latest email
curl -s "$API/inbound/api/emails?inboxEmail=$EMAIL" \
-H "X-API-KEY: $OPENINBOX_API_KEY" \
| jq -r '.emails[0] | "\(.from) — \(.subject)"'
# The HTML body (e.g. to assert a branded template or a button)
curl -s "$API/inbound/api/emails?inboxEmail=$EMAIL" \
-H "X-API-KEY: $OPENINBOX_API_KEY" | jq -r '.emails[0].htmlBody'
# Page through a busy inbox
curl -s "$API/inbound/api/emails?inboxEmail=$EMAIL&page=2&limit=20" \
-H "X-API-KEY: $OPENINBOX_API_KEY" | jq '{ total, totalPages }'Running it in CI
Because it is just HTTPS, the script drops straight into any pipeline. Store the key as a secret and expose it as OPENINBOX_API_KEY.
name: Email smoke test
on: [push]
jobs:
smoke:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: sudo apt-get update && sudo apt-get install -y jq
- run: ./otp.sh
env:
OPENINBOX_API_KEY: ${{ secrets.OPENINBOX_API_KEY }}Common pitfalls
- •Always bound the loop (the for/seq pattern above) and use set -euo pipefail — an unbounded while in CI will hang the job if no email arrives.
- •The list lives under .emails — read .emails[0].textBody, not the root. jq -e is handy to fail fast when a field is missing.
- •Creating an inbox needs no key; the poll needs -H "X-API-KEY: ...". A 401/403 from the poll means the key is missing or the plan is not premium.
- •grep -oE '[0-9]{4,8}' returns the first digit run, which could be a year or an ID. If the body has other numbers, anchor the pattern (e.g. grep -oE 'code [0-9]{6}').
- •If an inbox address could contain characters like + , URL-encode it (jq -rR @uri) before putting it in the query string.
Frequently Asked Questions
How do I get a temporary email from the command line?
Run curl -s -X POST https://api.openinbox.io/api/inbox — no auth required — and parse the email field with jq. The response also includes id and expiresAt.
Do I need an API key for curl?
Creating the inbox is unauthenticated. Reading received emails (GET /api/inbound/api/emails) needs a premium key sent as -H "X-API-KEY: $OPENINBOX_API_KEY".
How do I extract the OTP with curl and jq?
Pipe the body to grep: jq -r '.emails[0].textBody' | grep -oE '[0-9]{4,8}' | head -1. There is no parsed code field — it is a regex on textBody.
How do I wait for the email to arrive?
Loop the poll request with a short sleep and a bounded counter (see otp.sh), checking jq '.emails | length' each iteration. Emails usually arrive in 2–5 seconds.
Can I use this in CI/CD?
Yes — the script only makes HTTPS calls, so it runs on any runner. Install jq, store the key as a secret, and expose it as OPENINBOX_API_KEY.
How long does the inbox stay alive?
Free inboxes expire after one hour. Create a new one per script run so checks stay independent.
Related Pages
Explore More
Your private inbox is one click away
Free, instant, no registration needed. Works with any service. Expires automatically after 1 hour.
