Why Era

A whole company to build against.

Era runs a synthetic company inside the systems your product integrates with. Each one answers like the vendor it imitates, over REST and MCP. The data is the same on every run, and you can push the whole company forward a quarter. Nobody's real records are in it, and you need an account with none of the vendors to reach it.

·systems in the fleet
·buildable on this console
·carry the deep corpus
91days from day1 to day2
0real records, anywhere
Free for builders · every environment is 100% synthetic
The problem

Integrations and agents have nowhere to run.

Code that reads a customer's CRM, files a ticket and answers questions out of chat needs somewhere to live while you write it, and something to assert against once you have. There are three usual answers, and all three cost more than they look.

A customer's real tenant

Real records, real people, and a credential that reaches them. You cannot put that in CI, you cannot demo on it, and a write that goes wrong lands on somebody's business.

✕ not safe to automate

A vendor sandbox

Credentials no CI job should be holding. Data that reads differently next week. Rate limits your test matrix will trip. And no way to say: it is next quarter now, and the renewal closed.

✕ drifts under the suite

Hand-written mocks

A mock answers the calls you thought of, in the shapes you thought of. And it agrees with nothing: the account in your CRM fixture appears in no ticket and on no call, so there is nothing to grade a cross-system answer against.

✕ agrees with nothing
Era is the fourth option. The company is nobody's, you reach it with a token it issues you, and it reads the same tomorrow.
Who it is for

Three jobs, one company.

01

Integration and connector teams

You can only test a sync if you can move time. Read the estate, push it forward a quarter, read it again: the difference is what your incremental sync should have picked up. Throttling, latency, 500s and a blown quota are one admin call away on a simulator you run yourself, so the retry paths get exercised instead of assumed.

Testing & CI · day-states, faults, tenants
02

Agent builders and evaluators

Every system runs an MCP server next to its REST API, so an agent works this estate the way it would work a customer's. Writes are refused unless you ask for them, which is what makes an agent under test safe to run at all. A frozen company also comes with its ground truth recomputed, so you can score the answer you got.

MCP · one endpoint per system
03

Teams that have to show the product

Pick the industry, the size and the systems your audience actually runs, and Era stands up a company they will recognise: customers, deals and two years of history that line up instead of placeholder rows. When the call ends, throw it away.

Generate a company · in the browser
How it works

Describe a company, then point clients at it.

describeAn industry, a business model and a size - the vocabulary this console builds. The size is the company's own scale: its tiers name the customer book and the headcount.
pickThe systems it runs on, from the fleet this deployment serves - its catalog.
buildOne synthetic company is generated from that description and written into every system you picked, which is why they agree with each other. The environment is yours alone: an isolated tenant with its own token, or a token scoped to one system.
connectEach system answers its vendor's REST API and an MCP endpoint at /mcp on the same origin, with your token as the credential in the header that vendor reads. The console speaks MCP itself, so an agent can build the environment as well as work in it.
On your machine

One command, endpoints in .env

The CLI signs in through this console, provisions the environment and writes every system's endpoint and the tenant's token where your agent already looks for them.

In CI

The same simulators, offline

Released systems are published as images, one per system, so a suite composes the estate it needs and runs with no console, no network and no credential to leak.

How the data is made

The company comes first. The systems are views of it.

Synthetic data is usually made one system at a time. A script fills a CRM with plausible-looking rows, another script fills a helpdesk, and neither one has heard of the other. It holds up until a test asks a question that crosses a boundary. Era works the other way round. The company is built first: its people, its customers, the deals those customers signed, the tickets they filed, the calls they sat on, and the files and chat that came out of all of it. Every system then serves a slice of that one company in its own vendor's schema.

One seeded graph customers deals tickets calls messages files people the company
projected from the company records that name each other

A seed, a clock and a day-state are the whole input. Give it the same three and you get the same company back, down to the ids, so a count you assert on today is still right next month.

Each vendor's own schema
SalesforceAccount · Contact · Opportunity · Task
ZendeskOrganization · User · Ticket · Comment
SlackChannel · Message · File
GongCall · Transcript · Interaction stats
HiBobEmployee · Work history · Time off
S3Bucket · Object · Version
and the rest of the fleet

The requester on a Zendesk ticket is a contact at the account the Salesforce opportunity names, and the agent who answered is the employee HiBob has on that team. The ids match because there is one company underneath, not three.

Why that beats a row generator

Coherence is the obvious win. It is not the interesting one. Once the company is a graph and not a pile of tables, you can model the things that make real data awkward, and those are the things software gets wrong. About forty modules do nothing else: the working week, public holidays country by country, where people sit, job levels and job families, promotions and transfers, leave, churn and win-back, the demand funnel, on-call rotations, how free text is actually worded.

What a test or an agent asksRows-in-a-table synthetic dataHere
Whose ticket is this? An account id that appears nowhere else. A contact at a customer the CRM also books, who was on the call about it.
When was it created? Uniform random over the window, holidays and midnight included. Sampled in the record's own timezone: weekday-heavy, office hours, a lunch dip, a thin evening tail, almost nothing on a public holiday.
Who reports to whom? A flat list of titles, and a title is prose. Levels and job families derived as data, so a program can tell that one title outranks another instead of matching substrings.
Has anything ever changed? Everyone was hired once and never moved; every logo is still a customer. Promotions, transfers and reorganisations behind the roster; customers that went dormant, downgraded, churned with a reason, or came back.
Do two products agree on a number? Each one invented its own, so the ad clicks and the sessions in the traffic reports describe different companies. One funnel underneath: the same demand shows up in the ad platform, the traffic reports, the search console and the CRM's leads.
What does the text actually say? Lorem ipsum, or the subject line pasted into the body. Bodies written out of the record's own entities: the account, the error code, the person who filed it. Deterministic, and no model call at build time.
What does next quarter look like? Generate again with a different seed. It is a different company. The same company, 91 days on, moved once across every system at the same time.
None of that is taken on trust. Whether the estate agrees with itself is asserted in the suite: the account an opportunity names has to be the account the ticket was filed by and the account the incident fired on. Every earlier version of the graph broke in that same way, and every time it was a human who found it, reading two responses side by side.
Why this is hard

There is no generic simulator. Somebody has to write each one.

The shared graph took a while. It is nothing next to the part after it, which is making each system behave the way its vendor does, closely enough that the vendor's own client runs against it with only the base URL changed. That work does not generalise. It is one product at a time, and it is most of what is in the tree: about a million and a half lines of Python behind the fleet, and another million in its tests.

Per-vendor surface

Routes, query languages, pagination, errors

SOQL here, JQL there, a Postgres wire protocol somewhere else. Cursor pagination in one product, offsets in the next, and everybody's own error envelope: a Slack ok:false, an S3 REST-XML fault, a Salesforce error array. Get any of it wrong and the SDK you wanted to test with throws on the first call.

Credentials

One token, every vendor's idea of a header

The console mints one tenant-bound token. Then every connector has to declare how its real client would present it, because none of them agree: CircleCI reads Circle-Token, PagerDuty wants Authorization: Token token=…, LaunchDarkly takes a bare header, AWS expects a SigV4 credential scope. OAuth codes, device codes and sessions are minted and recorded per tenant too, since the login flow is part of what a client exercises.

Two surfaces, one policy

MCP cannot be the wider door

Every system publishes MCP tools next to its REST methods, off the same token. A tool that skipped the scope check would be a wider door than the method it mirrors: a grant the API answers 403 to would drive the whole product through /mcp. So a tool is held to the scope its REST equivalent needs, and the refusal comes back as a protocol error, because by then the session is authenticated.

Moving time

One quarter, agreed by everybody

Advancing a tenant used to mean every simulator inventing its own delta, and the deltas agreed about nothing. A helpdesk gained a ticket, the CRM gained an account nobody had ever met, no calendar moved at all, and the staff never changed. The quarter is computed once from the company now and handed to all of them. A sync window is only worth testing if everybody moved together.

Proof

The vendors' own test suites, pointed at us

Fidelity is easy to claim, so it gets checked with code nobody here wrote. zenpy's Zendesk suite runs with its cassettes flipped to record mode, which puts the requests it once recorded against a real account back on the wire. psycopg 3's own suite is written against a server and not against the driver, so it can be pointed at the Postgres simulator. Then stripe-python, the Jira client, elasticsearch-py, minio-py, pymysql, clickhouse-connect, and the vitest suites from vercel-labs/emulate. Every upstream is pinned, and every connector carries an audit file saying what was probed, what was broken, and which test pins the fix.

What makes it different

What a mock cannot give you.

Fidelity

Its vendor's own surface, not a stub

Each system serves its own product's routes, query language, pagination, credential header and error envelope: a Slack ok:false, an S3 REST-XML fault, JQL, SOQL, a SQL statement. Change the base URL and the vendor's own SDK talks to it, which is what the upstream client suites are there to prove. And each one says what it is at /_meta, so a client never has to guess.

Coherence

One company, every system

The whole estate comes out of one synthetic company graph. The account in the CRM is the account the ticket and the recorded call point at, and the people in chat are the people in the HR directory. An answer that needed three systems is one you can check.

Determinism

The same estate on every run

A tenant's data is a function of its seed, its clock and its day-state. Assert on a count today and it is still true tomorrow. Nothing is fetched from a vendor, so nothing drifts under the suite while you are not looking.

Time

A quarter you can step through

Three points in the company's life, and advancing moves every system at the same time: people hired and gone, customers signed, expanded and churned, deals moved on, and a quarter's worth of tickets, files, calls and messages. The three states are a cycle, so advancing past day2 puts the tenant back to empty, and you can jump straight to the one you want.

day0 · Inception day1 · Today→ 91 days → day2 · Next quarter
Breadth

A fleet, not one vendor with a coat of paint

It spans the SaaS and infrastructure systems this deployment serves, from CRM, support, chat and calls to file stores, clouds, databases, observability and CI.

MCP-native

An agent works this estate over MCP

MCP is not bolted on for a demo. Every system publishes its tools over streamable HTTP at /mcp, a write comes back as a protocol error while the tenant is read-only, and the console has account and provisioning tools of its own. So an agent can open an account, build its environment and then work in it without leaving the protocol. Moving the company a quarter is the one thing it steps out for: that is a call on the console's API.

Where it does not fit

What Era is not.

Every environment is 100% synthetic: no real records, no real people. It is no substitute for a staging system that carries your customers' data. And each system is vendor-shaped, not the vendor. It is not affiliated with, endorsed by or sponsored by any product it models, and it implements the surfaces a client uses, not every corner of an API. Read what a simulator is not before you let a released assertion depend on one.
Get started

Build one and point something at it.

Era is open to builders one account at a time.