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.
| Observation | What it establishes | What to check next |
|---|---|---|
| No message in the destination inbox | The retrieval path has no mail to inspect | Portal delivery and forwarding |
| Message exists, no suitable parsed code | Receipt alone is insufficient | Template, category and extracted fields |
HTTP 200 with code | A matching parsed code was returned | Correct attempt and portal acceptance |
| HTTP 408 | No suitable code was found before the wait ended | Delivery, 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