# Temporary Email Inbox & OTP API for AI Agents (`hirepulse/temporary-email-inbox`) Actor

Create private temporary email inboxes, list received-message metadata and extract numeric verification codes as JSON. Built for authorized QA, n8n and AI agents. Inbox TTL 1–60 minutes. Pay through Apify; no separate service account or crypto wallet required.

- **URL**: https://apify.com/hirepulse/temporary-email-inbox.md
- **Developed by:** [HirePulse](https://apify.com/hirepulse) (community)
- **Categories:** Developer tools, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 10-minute inbox allocations

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Temporary Email Inbox & OTP API for AI Agents

<img src="https://api.apify.com/v2/key-value-stores/kuV6wsPUC0FgeS20K/records/logo.png" alt="HirePulse private email inbox logo" width="160" height="160">

Create a private temporary email address, receive test emails and extract numeric verification codes as JSON. Use it for authorized QA of email verification flows, staging applications, n8n workflows and AI agents. The inbox receives real SMTP email; each inbox belongs to the Apify account that created it.

**No separate HirePulse account, API key or crypto wallet is needed. Billing is handled by Apify.** This Actor receives email; it does not send email, register accounts or complete verification on other websites. Temporary email domains may be rejected by external services.

### Watch the workflow

![Real Apify test runs: create inbox, pending status, extract a synthetic code, delete inbox](https://api.apify.com/v2/key-value-stores/kuV6wsPUC0FgeS20K/records/demo.gif)

11-second sequence of actual Apify Console screenshots from successful owner test runs: **create → pending → code → delete**. The disposable test email was injected through the signed relay, not sent over SMTP; this clip demonstrates the Actor and backend workflow. Waits are trimmed, and the private account sidebar and mailbox capability are excluded. Owner test-run usage shown in the Console is not the customer price; see pricing below.

### Quick start

Run with:

```json
{"action":"create","ttl_seconds":600}
```

The Actor returns immediately with a private random email `address`, `inbox_id`, `capability` and `expires_at`. Send your authorized test email to that address using your application's normal email flow. Then run this Actor again from **the same Apify account**:

```json
{
  "action":"get_code",
  "inbox_id":"REPLACE_WITH_INBOX_ID",
  "capability":"REPLACE_WITH_PRIVATE_CAPABILITY",
  "wait_seconds":30
}
```

The capability field is marked as a secret input. Never paste a real capability or verification code in a public Issue, support screenshot, task example or shared dataset.

### What you can do

| Action | Result | Requirements |
| --- | --- | --- |
| `create` | Random inbound address, inbox ID, private capability and expiry | `ttl_seconds` from 60 to 3600; default 600 |
| `get_code` | Numeric candidate with provenance, or an explicit pending/no-code/ambiguous state | Inbox ID and capability; optional wait up to 30 seconds |
| `list_messages` | Up to 50 message metadata records; no raw body, sender, subject or attachments | Inbox ID and capability |
| `delete` | Delete live inbox message candidates and revoke further reads | Inbox ID and capability |

### Pricing and spending limits

Every Actor start costs **$0.001**, including read, list, delete, invalid-input and failed runs. Creating an inbox additionally costs **$0.01 per started 10 minutes of requested lifetime**. There is no charge per received message or extracted code. Standard run compute is covered by these event prices; post-run storage/API usage follows Apify's platform pricing.

| Operation | Total event price |
| --- | --- |
| Create an inbox for 1–10 minutes | $0.011 |
| Create an inbox for 11–20 minutes | $0.021 |
| Create an inbox for one hour | $0.061 |
| One get-code run, with up to 30 seconds waiting | $0.001 |
| One list-messages or delete run | $0.001 |

Set `maxTotalChargeUsd` to at least $0.011 for a 10-minute create run or $0.061 for one hour. The Actor checks this limit before allocation. Creation retries within the same Actor run reuse the same inbox; they do not deliberately allocate or charge a second inbox. Starting a **new** create run creates another inbox and incurs its own fee. An uncertain charge is not automatically submitted again.

You buy a time-limited inbound address, not guaranteed email delivery or a working OTP. An inbox with no arriving email still incurs the allocation charge. No automatic no-message refund is implemented.

### Output examples

Create (illustrative values only):

```json
{
  "action":"create",
  "status":"active",
  "inbox_id":"00000000000000000000000000000000",
  "address":"example-only@example.invalid",
  "capability":"REDACTED_PRIVATE_CAPABILITY",
  "expires_at":1900000600,
  "allocation_price_usd":0.01,
  "run_start_price_usd":0.001
}
```

No email yet:

```json
{"action":"get_code","inbox_id":"00000000000000000000000000000000","status":"pending","code":null,"provenance":[],"run_start_price_usd":0.001}
```

When a supported numeric code is found, `status` is `code`, `code` contains the candidate and `provenance` contains its message ID, receipt/expiry timestamps, `source: "signed_relay"`, `sender_verified: false` and extraction method. SMTP sender identity and code validity are not verified.

### Input reference

- `action`: `create` (default), `get_code`, `list_messages`, or `delete`.
- `ttl_seconds`: integer 60–3600; default 600; used by create only.
- `inbox_id`: 32 lowercase hex characters; required for an existing inbox.
- `capability`: 64 lowercase hex characters; required for an existing inbox; encrypted secret input.
- `message_id`: optional 32-character ID from metadata; selects one message for get_code.
- `wait_seconds`: integer 0–30; default 0; get_code only. Polling is bounded and sleeps between requests.

### Code extraction and statuses

The parser conservatively recognizes **4–8 digit numeric codes** near verification/security/one-time-code/OTP labels, including supported Hebrew verification labels. Plain text and HTML text are parsed; scripts and attachments are not executed. Alphanumeric codes, magic links, QR codes, arbitrary email text and attachments are not returned.

- `pending`: no retained message candidate yet.
- `no_code`: retained message has no supported code.
- `ambiguous`: more than one candidate; use list_messages and select `message_id` when appropriate.
- `code`: one numeric candidate; verify suitability in your authorized application.
- Expired/deleted inboxes fail with `inbox_expired_or_deleted`; wrong account or capability fails without exposing another account's mailbox.

### Privacy and retention

Backend ownership is derived from the platform's Apify user ID, never an input field. Both the default dataset and key-value store are explicitly set to **RESTRICTED** before any inbox credential or code is persisted. The Actor fails if these permissions cannot be applied. Results are stored only in your run's restricted output, dataset and recovery state; operational logs omit addresses, capabilities, message bodies and codes. Users with explicit access to your Apify resources may still read them, so do not share sensitive run access.

Inbox lifetime is at most one hour. Retained code candidates expire after at most five minutes, or earlier when the inbox expires or is deleted. The backend does not retain full message bodies. **Apify copies of results follow Apify storage retention**, which can outlast the inbox lifetime; deleting a mailbox does not delete previous Apify run output. Remove sensitive run storage when no longer needed. Provider recovery snapshots may outlast live deletion.

Limits per Apify account: 20 active inboxes, 1000 retained inbox records, 50 distinct messages per inbox and 120 backend requests per minute. Retry 429/temporary errors with backoff. No arbitrary recipient name or custom domain is accepted.

### API, MCP and n8n

Run through Apify API with your Apify token in an Authorization header:

```bash
curl -X POST 'https://api.apify.com/v2/actors/hirepulse~temporary-email-inbox/run-sync-get-dataset-items?timeout=90&maxTotalChargeUsd=0.011' \
  -H 'Authorization: Bearer YOUR_APIFY_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"action":"create","ttl_seconds":600}'
```

For Apify MCP, select this Actor:

`https://mcp.apify.com?tools=hirepulse/temporary-email-inbox`

For n8n or Make: create inbox → save the returned ID/capability in private workflow credentials/state → trigger your authorized application's test email → call get_code with wait_seconds 30 → consume the candidate → delete inbox. Do not loop rapidly with new Actor runs; each run has the $0.001 start fee. Exported workflow examples must contain placeholders only.

### Troubleshooting and support

- `pending`: confirm the recipient is the allocated address and the inbox has not expired; external delivery may be delayed or rejected.
- `no_code`: the message may contain a link or an unsupported code format.
- `ambiguous`: inspect message metadata and choose a message ID; do not guess between candidates.
- `inbox_not_found`: check the Apify account, inbox ID and capability together.
- `run_budget_too_low`: increase the run limit to cover the stated event price; the automatic start fee still applies.
- `private_storage_required`: restricted storage access could not be confirmed; no mailbox allocation is attempted.
- `billing_confirmation_pending`: keep the run ID and contact support through the Actor Issues tab without posting credentials. Do not retry by creating multiple paid inboxes.

Use for systems and email flows you own or are authorized to test. Support is available in the Actor's Issues tab. Include the action and safe error code, not the mailbox capability, message contents, Apify token or OTP.

# Actor input Schema

## `action` (type: `string`):

Create returns address, inbox_id and capability immediately. Subsequent operations require both values and the same Apify account. get_code may return pending, no_code, ambiguous or code.

## `ttl_seconds` (type: `integer`):

Used only by create. 60–600 seconds: $0.01 allocation; 601–1200: $0.02; maximum 3600: $0.06, plus the $0.001 run start. TTL is fixed at creation.

## `inbox_id` (type: `string`):

32-character inbox_id from create. Required for get_code, list_messages and delete. Leave empty when creating.

## `capability` (type: `string`):

64-character private capability returned by create. Required for an existing inbox. Treat as a password; sent as an encrypted secret input. Ownership also requires the same Apify account.

## `message_id` (type: `string`):

Optional message_id from list_messages. Used only by get_code to choose one message when multiple deliveries are ambiguous.

## `wait_seconds` (type: `integer`):

Only for get_code. Wait at most 30 seconds, polling every 3 seconds. Use 0 for an immediate state check. Avoid repeated short-interval Actor starts; each start costs $0.001.

## Actor input object example

```json
{
  "action": "create",
  "ttl_seconds": 600,
  "wait_seconds": 0
}
```

# Actor output Schema

## `result` (type: `string`):

No description

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "action": "create",
    "ttl_seconds": 600
};

// Run the Actor and wait for it to finish
const run = await client.actor("hirepulse/temporary-email-inbox").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "action": "create",
    "ttl_seconds": 600,
}

# Run the Actor and wait for it to finish
run = client.actor("hirepulse/temporary-email-inbox").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "action": "create",
  "ttl_seconds": 600
}' |
apify call hirepulse/temporary-email-inbox --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,hirepulse/temporary-email-inbox"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/ZebWwUreCe8QYOqzp/builds/dA0oavULbRAqB0V2p/openapi.json
