An AI agent can receive an email OTP by routing the verification message into an inbox it can access, then reading the extracted code through an API. Lumbox provides that inbox and a GET /v1/inboxes/:id/otp endpoint that waits for a matching message for up to 120 seconds.

For a startup building agents that log into customer portals, the first question is where the portal sends its email. An agent-created account can use an agent-owned address. An existing customer account may still send codes to the customer’s mailbox. In that case, the customer needs to configure a suitable forwarding rule, or your application needs an authorized connection to that mailbox. Creating another inbox does not change the portal’s delivery address.

Establish the route before debugging the agent

Begin with one customer-authorized workflow and one known message template. Create a Lumbox inbox, save its returned ID and address, and arrange delivery to that address. The inbox documentation describes inbox management. Use the returned address instead of constructing one from a presumed default domain.

Then trigger a verification email in a test account you control. Inspect the received message before involving the browser agent. Check which address appears as the sender and whether forwarding changes the subject or body. A forwarding service can become the received sender, so filtering for the original portal’s domain may miss the forwarded message.

This separates a routing problem from an extraction problem. If the inbox contains no message, changing the model prompt will not repair delivery. If a message is present but has no extracted code, inspect its actual content and classification. If a code comes back but the portal rejects it, investigate the login attempt and expiry separately.

Make one bounded retrieval request

The following request assumes that the inbox already exists and mail is routed to it. Set LUMBOX_API_KEY, LUMBOX_INBOX_ID, ATTEMPT_STARTED_AT, and EXPECTED_RECEIVED_SENDER in your runtime. Capture the attempt timestamp immediately before requesting the portal’s code. The sender value should match what arrives in the destination inbox.

curl --get --max-time 130 \
  "https://api.lumbox.co/v1/inboxes/${LUMBOX_INBOX_ID}/otp" \
  -H "X-API-Key: ${LUMBOX_API_KEY}" \
  --data-urlencode "timeout=120" \
  --data-urlencode "since=${ATTEMPT_STARTED_AT}" \
  --data-urlencode "from=${EXPECTED_RECEIVED_SENDER}"

The server’s default timeout is 30 seconds. It clamps the requested timeout between 1 and 120 seconds. Configure the HTTP client and any proxy to permit the intended wait, with some transport margin. A client that gives up earlier can hide the server’s eventual result.

The API reference is the public entry point. The inspected implementation returns code, all_codes, from, subject, expires, and email_id. Use code, not an assumed otp field. These names matter when an agent hands the response to deterministic application code.

Know what matching actually means

The endpoint looks for recent messages categorized as verification and returns the first extracted code from the newest matching message when codes are available. Without since, it uses a five-minute lookback. The optional from filter uses a substring match against the received sender address.

A sender filter is a retrieval filter. It is not proof that a message belongs to a particular browser run. A timestamp narrows the window, but two overlapping attempts against the same account can still fall inside it. Keep the relationship between customer, portal account, browser session, inbox and attempt in your application.

ObservationWhat it establishesWhat to check next
No message in the destination inboxThe retrieval path has no mail to inspectPortal delivery and forwarding
Message exists, no suitable parsed codeReceipt alone is insufficientTemplate, category and extracted fields
HTTP 200 with codeA matching parsed code was returnedCorrect attempt and portal acceptance
HTTP 408No suitable code was found before the wait endedDelivery, filters and parser output

Lumbox’s parser uses patterns and category rules. This is useful for predictable automation, but it is not a promise that every email template will match. Test the exact messages your buyers receive, including the forwarded version. The email documentation covers the structured message representation.

Treat a timeout as an application decision

A timeout returns HTTP 408 with error: "No OTP found" and the timeout value. It does not tell you whether the portal failed to send, forwarding was delayed, the filter excluded the message, or parsing produced no suitable result.

Record the stage that failed without putting the code or full email body in ordinary logs. A useful diagnostic record includes the attempt ID your application owns, the inbox ID, request start time, response status and whether the browser remained on the challenge screen. Store sensitive message content only where your support process needs it.

Decide in advance whether to retry retrieval, request another code, or hand control to the customer. Requesting another code may change what the portal accepts. That behavior belongs to the portal, so a generic retry loop should not assume older codes remain valid.

Fit retrieval into the browser workflow

Once you have a candidate code, check that the browser still represents the intended account and challenge. Supply the code through your browser controller, then inspect a defined success condition such as the authenticated account page. A successful inbox read and a successful login are different events.

Your application should also remember completed attempts. The OTP endpoint is not a consume-once queue, and another request can return the same recent message. Preventing duplicate use or simultaneous submissions is your orchestration responsibility.

This pattern is a good fit when the missing part of a portal agent is receiving email and extracting a verification value. If your application already has authorized mailbox access and parsing that works for its templates, retaining that route may be simpler. Lumbox is useful when you want an agent-owned inbox and a bounded retrieval API without building the client polling loop yourself.

The server still polls its database internally once per second. “One call” describes the client’s retrieval step after provisioning and routing, not an entire login or an absence of polling anywhere in the system.

Implementation references, relative to the Lumbox repository: apps/api/src/routes/inboxes.ts (OTP and wait handlers), apps/api/src/utils/parser.ts (extraction and classification), and apps/docs/content/docs/api-reference.mdx (public reference source). Checked October 3, 2026.

Kumar