Personas
A persona is a synthetic identity — a believable name, gender, date of birth, country, locale and address — with its own working email address. You use personas to sign up for and operate accounts on the sites you scrape, and to receive the verification codes those sites email, without ever creating or managing a real mailbox yourself.
Personas are billed per persona per month and are created in real time — there is no pool or waiting; you ask for N in a country and you get them instantly, each with an email address ready to receive mail.
How the email works
Every persona’s address lives on a domain the platform owns (e.g.
clairemcguire@yourdomain.com). Those domains run a catch-all rule that
forwards all their mail to one central mailbox the platform controls. When a
site emails a persona, the message is forwarded to that mailbox, and the platform
serves it back to you filtered to just that persona’s address.
You never hold a mailbox password. The platform reads the central mailbox server-side and returns only the messages addressed to your persona. This is the mediated inbox model — you get the mail and the codes, never a credential that could take over an account.
Generating personas
Open the Persona Profiles tab in the dashboard and click Generate Personas. Choose:
| Field | Meaning |
|---|---|
| Count | How many to create (1–500). |
| Country | The identity’s country — drives the name pool, locale, timezone and address. Each persona is created in the country you pick. |
| Label | Optional tag to help you find them later (e.g. a campaign name). |
Each persona is created immediately with:
- A locale-correct identity (name, gender, date of birth, address).
- A unique, name-derived email address on one of the platform’s domains — for
Claire McGuire you’ll get something like
clairemcguire@…,claire.mcguire@…orc.mcguire@…, never random gibberish, and never a duplicate.
Click any persona in the list to open its detail panel: identity, email address (with copy), the inbox, and a free-form metadata editor where you can attach your own account fields (any key/value) — this is your data and is never read or used by the platform.
Inspecting a persona’s email
From a persona’s detail panel, click Open inbox to launch the full mailbox viewer. It is a proper two-pane mail client:
- Message list (left) — newest first, paginated, so it scales to any volume.
- Reader (right) — the selected message’s body, sender, date and any links.
- Spam coverage — the viewer searches both the normal folder and Spam, so
verification codes that get junked still show up (flagged with a
spambadge). - Find code — type a regex (default
\d{4,8}) and the viewer pulls the matching code out of the selected message with one-click copy.
Mail sent only via BCC carries no header trace of the persona’s address and can’t be attributed to a persona. Every normal To/Cc delivery is found.
API
The dashboard is built on a small REST API you can also call programmatically.
All routes are under /api/v1, scoped to your organization, and authenticated
with your platform (Auth0) access token:
Authorization: Bearer <access-token>Generate
POST /api/v1/personas/batch
Content-Type: application/json
{ "count": 5, "country": "MX", "label": "campaign-a" }Returns 201 with the created personas:
{
"personas": [ { "id": "…", "first_name": "Claire", "last_name": "McGuire",
"country": "MX", "email": { "address": "clairemcguire@…" },
"email_status": "ready", "status": "assigned" } ],
"requested": 5,
"created": 5
}List & read
| Method | Path | Purpose |
|---|---|---|
GET | /api/v1/personas | All your personas. |
GET | /api/v1/personas/{id} | One persona (identity + email address). |
PATCH | /api/v1/personas/{id} | Update label and/or attributes (your metadata). |
DELETE | /api/v1/personas/{id} | Retire it (stops next-cycle billing). |
Inbox
GET /api/v1/personas/{id}/inbox?limit=25&offset=0Returns a page of messages, newest first, across the normal and spam folders:
{
"messages": [
{ "uid": 1837, "folder": "inbox", "from": "no-reply@site.com",
"subject": "Your code", "date": "2026-07-01T04:11:32Z",
"snippet": "Your code is 483920 …", "text_body": "…",
"links": ["https://…"] }
],
"total": 3, "limit": 25, "offset": 0, "has_more": false
}Latest message + code extraction
The one call you’ll use most from automation — fetch the newest matching message and pull a code out of it in one shot:
GET /api/v1/personas/{id}/messages/latest?from=site.com&extract=\d{6}from— optional, case-insensitive substring match on the sender.extract— optional regex; the first capture group (or full match) is returned asextracted. The raw message is always returned alongside it.
{ "found": true,
"message": { "subject": "Your code", "from": "no-reply@site.com",
"text_body": "Your code is 483920", "extracted": "483920" } }Inbox reads are rate-limited per persona and every read is audit-logged. The platform warrants faithful delivery of your persona’s mail; extraction is your regex and is best-effort — the raw message is always returned so you can parse it yourself.
Using personas from crawlers
Spiders don’t use your dashboard login. They call a small crawler API under
/api/v1/crawler, authenticated with the short-lived, org-scoped job token the
platform already injects into every job as BROWSER_TOKEN — the same token
your browsers use. Nothing new to configure:
ISBACKEND_INTERNAL_URL— the API base URL (already injected).BROWSER_TOKEN— the org-scoped job token (already injected).
The token carries your org, so a spider only ever sees its own org’s personas and inboxes.
The example below is a complete, self-contained spider pattern — list personas, paginate inboxes, read a full email, and extract a code — using only the two injected environment variables and the standard library.
List your personas
GET {ISBACKEND_INTERNAL_URL}/api/v1/crawler/personas
Authorization: Bearer {BROWSER_TOKEN}Returns your org’s active personas, each with identity + email address:
{ "count": 12,
"personas": [ { "id": "…", "first_name": "Claire", "last_name": "McGuire",
"country": "MX", "email": { "address": "clairemcguire@…" } } ] }Read a persona’s inbox (paginated, full emails)
GET {ISBACKEND_INTERNAL_URL}/api/v1/crawler/personas/{id}/inbox?limit=25&offset=0
Authorization: Bearer {BROWSER_TOKEN}Each message in the page carries the complete email — text_body,
html_body, links and snippet, plus a folder of inbox or spam — not
just metadata. Page with limit/offset; the response includes total and
has_more.
Read the newest email / extract a code
GET {ISBACKEND_INTERNAL_URL}/api/v1/crawler/personas/{id}/messages/latest?from=site.com&extract=\d{6}
Authorization: Bearer {BROWSER_TOKEN}Returns the newest matching message in full. extract is optional — with it
you also get extracted (the code); without it you still get the whole body, so
you can read or validate the entire email yourself.
Example — inside a spider (urllib, no extra deps)
import json, os, urllib.parse, urllib.request
BASE = os.environ["ISBACKEND_INTERNAL_URL"].rstrip("/")
TOKEN = os.environ["BROWSER_TOKEN"]
def api_get(path, params=None):
url = BASE + path + (("?" + urllib.parse.urlencode(params)) if params else "")
req = urllib.request.Request(url, headers={"Authorization": f"Bearer {TOKEN}"})
with urllib.request.urlopen(req, timeout=30) as r:
return json.load(r)
# 1. Pick a persona.
persona = api_get("/api/v1/crawler/personas")["personas"][0]
pid, email = persona["id"], persona["email"]["address"]
# 2. Read its inbox — every message includes the full body.
page = api_get(f"/api/v1/crawler/personas/{pid}/inbox", {"limit": 25, "offset": 0})
for m in page["messages"]:
print(m["folder"], m["from"], m["subject"], len(m.get("text_body") or ""))
# 3a. Read the newest email IN FULL (no extraction).
full = api_get(f"/api/v1/crawler/personas/{pid}/messages/latest")["message"]
print(full["text_body"]) # the complete email body
print(full.get("links", [])) # and its links
# 3b. Or pull a verification code out of the newest message.
res = api_get(f"/api/v1/crawler/personas/{pid}/messages/latest", {"extract": r"\d{6}"})
code = (res.get("message") or {}).get("extracted")The whole loop: generate personas (dashboard or API) → your spider lists them
and reads the identity + email → signs the persona up on the target site →
reads the inbox (full email) or polls messages/latest for the code →
continues. No mailbox to manage, no credentials to hold.
Optional — personas in your addon database
If your project has the Postgres addon, the platform also projects your
personas into your addon database as a read-only personas table, kept in
sync automatically. So identity + email is a plain SQL query over the DSN your
spiders already use — no HTTP:
import os, psycopg2 # your addon DSN is injected as an env var
conn = psycopg2.connect(os.environ["POSTGRES_URL"]) # your injected addon DSN
cur = conn.cursor()
cur.execute("""
SELECT id, first_name, last_name, email_address, country
FROM personas
WHERE email_status = 'ready' AND country = %s
ORDER BY updated_at DESC LIMIT 1
""", ("MX",))
persona_id, first, last, email, country = cur.fetchone()Columns: id, first_name, last_name, gender, date_of_birth, country, locale, timezone, address (jsonb), email_address, status, email_status, attributes (jsonb), updated_at. Retired personas are removed. The table never contains a
mailbox credential — there isn’t one. Use persona_id with the inbox API above
to read mail; a live mailbox read stays behind the API (it’s not static data).