Sim Studio, now simply called Sim, is an open-source workspace for building AI agents. You build a workflow visually by connecting blocks (Agent, API, Function, Condition, Parallel and others), describe one in its Chat, or trigger it through its API, and run it on sim.ai or self-hosted. Its integration catalog covers Gmail, Slack and a long list of services, but not an inbox your workflow can create on demand and throw away. For a flow that has to pass an email verification step, that is the missing piece.

Lumbox is not a native Sim integration, so this post connects it the two ways Sim offers for any REST API: API blocks for a fixed sequence of steps, and a custom tool when an Agent block should decide when to check mail.

Store the key

Add your Lumbox key under Settings → Secrets as LUMBOX_API_KEY. Sim substitutes {{LUMBOX_API_KEY}} in any block field at run time, keeps the value out of the saved workflow, and masks it in execution logs. A workspace secret is visible to all members; a personal one only to you.

The flow as API blocks

Sim's API block makes one HTTP request and exposes data (the parsed JSON body), status and headers to later blocks, referenced by block name as <blockname.field>. Rename each block to a single lowercase word so the references stay readable.

BlockTypeConfigurationUsed later as
createinboxAPIPOST https://api.lumbox.co/v1/inboxes, body {}<createinbox.data.id>, <createinbox.data.address>
stampFunctionreturns the current time minus a few seconds<stamp.result>
(your signup step)anysubmits the form with the address
waitotpAPIGET https://api.lumbox.co/v1/inboxes/<createinbox.data.id>/otp, query timeout=120, since=<stamp.result><waitotp.status>, <waitotp.data.code>
gotcodeConditionbranches on <waitotp.status> being 200
cleanupAPIDELETE https://api.lumbox.co/v1/inboxes/<createinbox.data.id>

Every Lumbox API block gets the header X-API-Key: {{LUMBOX_API_KEY}}, and the POST also gets Content-Type: application/json. The stamp Function block is one line of JavaScript:

return new Date(Date.now() - 5000).toISOString();

Why a timestamp block at all: the OTP endpoint returns the newest verification email received after since, and without it, it looks back five minutes. If the flow ever resends a code into the same inbox, or a test run reuses an inbox, the five-minute window can hand back the previous code. Stamping the time just before the signup step and passing it as since ties the wait to this attempt. The five seconds cover small clock differences.

How the wait behaves in Sim

GET /v1/inboxes/:id/otp is a long-poll. Lumbox holds the request, checks for new mail every second, and answers 200 with { code, all_codes, from, subject, expires, email_id } as soon as a code arrives, or 408 when timeout seconds pass (the server caps it at 120). The API block's own timeout defaults to five minutes, so it will not cut the request off first.

A 408 is not an error to Lumbox; it means no code arrived yet. Sim's docs suggest branching on <api.status> with a Condition block and connecting the block's error path for network failures, and this flow uses both: gotcode sends a 200 to the step that enters <waitotp.data.code>, while any other status, and the error path, go to a branch that clicks "resend" and waits again or ends the run with a clear message. The API block's retry settings apply to timeouts, 429s and 5xx responses, so do not count on them to repeat a wait that ended in 408.

Leave retries off for createinbox. Sim does not retry POST requests unless you enable it, which is the right default: a retried create would make a second inbox. If you do enable it, add an Idempotency-Key header built from the run, and Lumbox will return the original inbox for a repeated key and body within 24 hours.

Running many at once

A deployed Sim workflow can be called many times concurrently, and a Parallel block runs instances side by side with separate variable scopes. Because each execution runs its own createinbox, each gets its own address, so one run's code cannot be read by another. That is the practical difference from pointing every run at one shared mailbox, where concurrent signups to the same service produce several nearly identical emails and each run has to guess which is its own.

The limit to plan for is inbox count. Each open inbox counts toward your plan (3 on Free, 10 on Starter, 50 on Pro, 250 on Scale), and createinbox returns 402 with PLAN_LIMIT_EXCEEDED once you are at the cap. The cleanup block keeps the count down; make sure the failure branches reach it too, not only the success path.

The Agent-block version

When an Agent block is driving the task and should decide for itself when to wait for mail, give it a custom tool instead. Under Settings → Custom Tools, define a schema in OpenAI function-calling format with inbox_id and since parameters, and this code:

const qs = new URLSearchParams({ timeout: "90", since });
const res = await fetch(`https://api.lumbox.co/v1/inboxes/${inbox_id}/otp?${qs}`, {
  headers: { "X-API-Key": {{LUMBOX_API_KEY}} },
});
if (res.status === 408) return { code: null, note: "No code yet" };
const body = await res.json();
return res.ok ? { code: body.code } : { error: body.error };

Custom tool code runs in a sandbox with fetch and Node built-ins but no npm packages, so it calls the REST API directly rather than the lumbox SDK. Schema parameters are plain variables, and {{LUMBOX_API_KEY}} is bound as a string at execution time. A matching create_inbox tool is the same shape with a POST. Returning code: null on a 408, instead of throwing, lets the model choose to request a new code.

Limits of this setup

The OTP endpoint finds numeric codes of 4 to 8 digits near words like "code" or "verification", in emails categorised as verification mail. A service that sends only a confirmation link needs an API block on GET /v1/inboxes/:id/wait (same headers, same since) and the link from <blockname.data.parsed.verification_links>. Nothing in this flow fills in a third-party form; that is whichever browser automation or API step you already use. And the Free plan's new-account sending ramp only matters if the workflow also sends mail from the inbox, which this one does not.

The quickstart covers getting a key, the n8n version builds the same flow from HTTP nodes, and inbox isolation goes further into one inbox per run. Plan limits are on the pricing page.