New: How we build — modern AI tooling, strict guardrails, every line reviewed by a person. Read our engineering practices →New: How we build. AI tooling, strict guardrails, human review. Read more →

Software and platforms · Media and experiences

IQEX: a platform that generates with AI, and knows exactly what each generation cost

One platform for building interactive experiences, collecting information through forms, generating media and text with AI, and automating the work between all three. Underneath it: a credit economy that prices every AI action, records what the provider actually charged for it, and reports margin per customer.

  • 35 modules
  • 5 ways into one experience
  • 4 verdicts before a source is trusted
  • 2 wallets, one order
  • 1 codebase for every configuration

What the platform does

Three things that are usually three products.

Experiences people open with a phone. A timeline of screens, video, audio, images and buttons, built for portrait and landscape, playing in a browser with no app to install. The audience arrives by scanning a printed code, tapping a tag, walking within range of a place, pointing a camera at an object, or following a plain link.

Forms that do more than collect text. Questions branch on the answer. A question can be narrated aloud by an AI presenter, capture a location, collect a set of images, or link to a person, a place or a storyline held elsewhere in the platform. Answers land in one place and can flow onward into whatever system the customer already works in.

AI that produces the material. Images, video, voice-over and scripts, generated inside the platform and filed into the same library the experience editor draws from. Alongside it, a retrieval layer that answers questions from a customer's own documents rather than from the open internet.

And the automation layer that runs jobs across all three, from assembling a whole project to capturing a page.

Product
Multi-tenant B2B platform for interactive media, data capture, AI generation and automation
Users
Platform operators, organisation administrators, and the people inside those organisations
Audience
The public, who open an experience with a phone and never see the platform
Our scope
Platform architecture, credit and metering layer, AI and retrieval layer, experience player, outbound integrations, multi-tenancy

The one fact that shaped everything

Every meaningful action on this platform costs real money to somebody else the moment it happens.

An image generated, a script written, a voice-over produced, a question answered from a document. Each one is a call to a provider who invoices at the end of the month, and each one is sold to a customer at a price set before it happened.

That is a resale business, and resale businesses fail in a specific way. Not dramatically. They discover, a quarter late and from an invoice, that a popular feature has been sold below cost the entire time.

Price and cost have to be separate numbers.

What a provider charges and what a customer pays are different decisions, and conflating them means a provider changing their rates silently changes your margin.

Cost has to be recorded when it is incurred.

A price list is a live thing. A margin figure calculated from today's prices against last quarter's activity is fiction.

Consumption has to be visible before it is spent.

Both to the customer, who needs to know what a thing will cost, and to the operator, who needs to know a provider allowance is about to run out before it does.

The four decisions that mattered

If you read nothing else on this page, read this.

One
Price, cost and margin are three separate things the platform tracks

Not one number inferred from another.

Two
A source is tested before it is trusted

The verdict comes when somebody adds a document, not when somebody asks a question about it.

Three
The product surface is configuration

Thirty-five modules, and each customer sees the ones they bought.

Four
An integration that stops working says so

Every outbound send is a job with a state, and every connection has a health.

Decision one

Price, cost and margin are three separate things

The simple version of an AI platform charges a subscription and hopes usage averages out. It works until one customer generates ten thousand images, and then it works badly for everybody, because the response is either a surprise invoice or a quiet degradation of the service.

The metered version is honest and much harder to build. It requires the platform to know, for every model of every provider, what a call actually costs, and providers do not price the same way. Some charge a flat rate per call. Some charge by the character. Some by the image. Some by the request. A single credit price applied across that produces margin that varies by an order of magnitude depending on which feature a customer happens to like.

And the cost is a moving target. Providers change prices. A margin report built by applying today's rates to last quarter's activity describes a business nobody ran.

What we did

Supplier price and credit price are separate fields, set per provider and per model, with the cost model recorded alongside so a per-character service is not treated like a flat-rate one. The effective rate falls out of the two, and it is visible before anybody is charged.

The real cost is stamped onto each activity as it happens. An image generated in March carries March's provider cost forever. Nothing is recalculated from a price list that has since moved.

Provider health is monitored rather than discovered. Keys have a status and a verification date, because an expired key does not degrade the platform, it stops AI working for every customer at once. Prepaid allowances are watched with a warning before they run out.

Two wallets, one order. A person has their own balance and their organisation has a shared pool, personal is spent first, and the visible total is what is actually available. Card payment is handed to a payment provider on their own hosted page, so card details never reach the platform.

These are the actions that move money or change what customers are charged, performed by the smallest number of people and reviewed by nobody in the ordinary course of a day. They are exactly the ones a metered platform cannot afford to leave untraced, and an unlogged manual credit grant is the same category of gap as an unlogged refund would be anywhere else.

The record is written where the application cannot revise it, so it shows what happened rather than what the current configuration implies happened.

Impact

Margin is a fact rather than an estimate. Revenue against real cost of goods, per organisation, over any period, reconcilable back to individual actions.

A pricing mistake is visible in days rather than quarters. Effective rate per service means a feature sold below cost shows up as a number rather than as an unexplained gap at year end.

A dead provider key is caught before a customer meets it. Verification is an action somebody takes, not an incident somebody reports.

A margin figure can be defended, not just produced. Every credit in the ledger traces to either a purchase or a named grant, so a number that looks wrong has somewhere to be traced to rather than an argument to be had about it.

The compliance surface stays small. Card details are captured by the payment provider on their own page, so the platform holds a reference and never the instrument.

Decision two

A source is tested before it is trusted

The platform lets a customer build a pack of their own material, documents, web pages, recordings and pasted text, and then ask questions of it.

Retrieval systems fail quietly, and that is the whole problem. If a source did not load, the question still gets an answer. The answer is fluent, confident and missing whatever was in the document that was not there. Nothing errors, nothing is flagged, and the person asking has no way to know the difference between an answer drawn from twelve sources and one drawn from nine.

Web pages make it worse. A great many sites refuse automated readers, or require a sign-in, or return a page that technically loads and contains almost no text. All three look identical to a person pasting a link.

What we did

A verdict before the pack is saved. Testing a link returns one of four answers: it will read, it is blocked or needs a sign-in, it loads with almost no text, or it is dead. That happens while somebody has the source in front of them and can do something about it, rather than months later when nobody remembers where it came from.

A blocked source has an answer rather than a failure. If a site refuses robots, the text can be pasted in directly and the pack is complete anyway. The system tells the person what to do instead of what went wrong.

Indexing reports per source, not per pack. Progress, which step failed, when and why. And the extracted text is visible, so somebody can check what was actually read out of a file rather than assuming.

The same packs sit behind form questions, so a form can ask something answered from the organisation's own material.

Impact

A gap in the knowledge is found at add time, which is the only moment it is cheap to fix.

The failure stops being silent. The distinction between a pack that indexed and a pack that half-indexed is visible, which is the distinction the answer quality actually depends on.

Somebody can verify what the system read. Being able to see the extracted text is what turns a retrieval feature from something people trust into something they can check.

Answers are grounded in the customer's material rather than the open internet, which for a research tool is the difference between a product and a subscription to somebody else's model.

Decision three

The product surface is configuration

Thirty-five modules is a great deal of product, and no customer needs all of it. A museum building location-triggered experiences has no use for billing reports. A training provider collecting form data does not need a media timeline editor.

Shipping everything to everybody is not neutral. Every module a customer does not need is a thing they have to learn to ignore, and a support conversation waiting to happen.

The usual answer is a build per segment, or a set of feature flags that accumulate until nobody can say what a given customer actually has. Both end the same way: several products with one name, and a fix that reaches most of them.

What we did

Two things decide what a person sees. Their role, which governs what they may do and which figures they are shown, and their organisation's settings, which govern which module groups exist for that customer at all.

Roles are three, not a matrix. Somebody who runs the platform, somebody who runs one customer account, and somebody who works inside one. Each sees a different scope of the same screens rather than different screens.

One module is always present, so no configuration can produce an empty application.

The same principle runs everywhere else. Categories, defaults, credit packs, prompt templates and automation recipes are all data. An automation is defined once, given a form to collect its inputs, a credit cost and a category, and it appears for the people entitled to run it.

Impact

A new customer is set up rather than built for. Selling to a museum, a training provider and a marketing team is three configurations, not three roadmaps.

A fix reaches everybody. One codebase means no segment quietly running an older behaviour.

The product each customer sees is honest about what they bought, which reduces both training and the support load that follows unclear scope.

Adding an automation does not require a release. Defining a recipe is data entry, so the platform's capability grows without its codebase doing the same.

Decision four

An integration that stops working says so

Form answers flow outward into the spreadsheet, database or document system a customer already works in. Setting that up takes a few minutes. It then runs for months with nobody watching it, which is where the real design problem lives.

Access granted to another service expires. That is not a fault, it is how those services are built. But an expired credential produces exactly the same visible result as a working one: nothing. No error reaches the customer, rows simply stop arriving, and the discovery is made weeks later by somebody looking for data that was never written.

What we did

Connecting hands authentication to the other service. The customer signs in there, and the platform never receives a password.

Field mapping is suggested and then corrected. Columns are proposed automatically and adjusted by a person, because a suggested mapping accepted without review is a data quality problem with a delay on it.

Every send is a job with a state. Synced, pending or failed, with the number of attempts and when the last one was, and a failed job can be pushed through again rather than re-entered by hand.

Every connection has a health. Active, paused, disabled or expired, with the last refresh shown and a reconnect action. Expiry is treated as an expected state rather than an incident.

Failures are counted in one place. How many connections exist, of what kind, and how many jobs have failed, so somebody can look at a number rather than wait to be told.

Impact

A gap lasts an hour rather than six weeks. Expiry surfaces as a status somebody can act on, which is the whole difference between the two.

Nobody re-enters data by hand. A failed send is retried rather than reconstructed from an inbox.

The customer keeps control of their own access. Authentication happens on their service, and disconnecting is theirs to do.

One form can feed several destinations, so a submission reaches a spreadsheet, a document and an inbox from a single fill.

Which criteria a metered platform lives on

Two of the five trust services criteria carry more weight here than the others, and neither is the one people reach for first.

Processing integrity asks whether a system does what it claims, completely and accurately. On a platform where money moves every time somebody generates an image, that is the whole business. A credit charged must correspond to an action that happened. An action must carry the cost the provider actually charged. A margin report must reconcile to the activities behind it rather than to an average, and nothing may change the ledger without leaving an actor, a time and a reason behind it. Cost stamped at the time of the activity, effective rate visible before billing, and a defined spending order across two wallets are all answers to this question rather than to a security one.

Confidentiality is the other. Customers upload their own documents into knowledge packs and their own material into asset libraries, on shared infrastructure, and one organisation's sources must never inform another organisation's answers. Retrieval is scoped to the packs a person selected, within the organisation they belong to.

The control set was designed against the criteria rather than mapped to them afterwards. That is a statement about how the platform was built. It is not a claim to hold an attestation, and where an operator needs one, the work is theirs to complete with an auditor.

The constraints we designed around

Platforms serving many customer types across many external services meet constraints. Some belong to providers who change their terms without asking. Some come from the phone in a visitor's hand. Some come from the fact that the audience is not the customer.

Building for all of them on day one is not prudence, it is waste. The work is knowing which to design for up front, which to address when they become real, and which are somebody else's decision to be routed around cleanly.

A phone will not play media it was not asked to play

The challenge. Mobile browsers block sound and video that start on their own. That is deliberate, it is not going away, and it means an experience cannot simply begin when somebody arrives.

What we did. Every experience starts with a single tap, and the media buffers before playback rather than during it. Where playback fails the visitor is told, rather than left watching an icon spin.

Impact

The experience works reliably on a phone in a doorway, which is where it is actually used. And the person holding the phone is standing in front of the thing the experience is about, so a failure they can understand costs far less than a failure they cannot.

The audience is not the customer

The challenge. The people who open an experience have no account, no relationship with the platform, and no interest in it. They scanned something. Anything that asks them to install, register or wait is a step at which most of them leave.

What we did. Everything runs in the browser. Access rules and any cost are settled before the first frame rather than partway through. A project can be open to anyone, protected by a password, or restricted to signed-in members, and which one it is does not change how it was built.

Impact

No app, no account and no wait for the general case, and the customer still gets the option to gate an experience when they need to.

Providers change their prices without asking

The challenge. The cost base of this platform is set by companies that are not on the call. Rates move, models are retired, keys expire and prepaid allowances run down.

What we did. Made supplier prices a maintained list that can be refreshed, kept the credit price a separate decision, and monitored key health and allowances rather than waiting for a failure.

Impact

A provider price change is an update rather than an outage in the margin. And the operator finds out an allowance is low from the platform rather than from a customer whose generation failed.

Media generation is slow, and a person is watching

The challenge. Generating an image, a video or a voice-over takes long enough that a person will wonder whether it is working. Generating a whole project takes longer still.

What we did. Longer work runs as a job with a visible run history rather than a request somebody waits on. Automations report what happened, including a build status, a link to what was produced, and a log when it is needed.

Impact

Somebody can start a job and come back to it. And when a run does not produce what was expected, there is a record of what it did rather than a shrug.

The impact, depending on your job

If you run the business

A metered model only works if the meter is trustworthy. Selling AI by the credit is easy to announce and hard to survive, and the difference is whether the platform can tell you what a customer cost you last month. This one can, per organisation, per period, back to individual actions.

Configuration rather than customisation is what makes the second customer profitable. A platform that needs a build per segment is a consultancy with a product-shaped invoice.

The audience never has to be acquired. Somebody scans a code and the experience opens. No install, no account, no funnel, which is the reason this model reaches people a mobile app never would.

If you run engineering

The metering layer is the part worth your attention. Separating supplier price from credit price, recording cost at the moment of the activity, and carrying the provider's cost model rather than flattening it are the three decisions that make margin reporting possible at all.

Then the retrieval layer, where the design work is in failing at add time rather than at answer time, because a retrieval system that fails at answer time does not fail visibly.

If you run a delivery team

Most of what is on this page came from deciding where complexity lives. Module visibility, categories, defaults, credit packs, prompt templates and automation recipes are data rather than code. An automation is defined rather than built.

That is what keeps a team shipping across thirty-five modules rather than maintaining a variant per customer type.

If you own the numbers

Cost of goods is known per action, so gross margin is a report rather than an exercise.

A mispriced feature surfaces as an effective rate, before it becomes a quarter.

Provider allowances are watched, so the failure mode is a warning rather than a service interruption with a customer attached to it.

Card details never reach the platform, which removes an audit scope permanently rather than managing one.

Talk to the client, not just to us

Everything on this page is our account of our own work. If you are seriously evaluating us, we will arrange a reference call with somebody who has been through a build like this one, and you can ask them the questions you would rather not ask us.

Request a client reference
Built with

Technologies we built with

We name the layers rather than the suppliers on the customer data path, because a supplier map is our client's exposure rather than our credential. Full detail available under NDA.

Backend
PythonDjangoMySQL
Frontend
Next.jsFabric.js
Cloud and infrastructure
AWSContainerised services
Platform
org-scoped modulesThree-role access control
Experience delivery
Browser-based playerPortrait and landscape timelinesCode, tag, location, camera, link
AI layer
Provider-agnostic routingCost stamped at point of useSupplier and credit price separate
Retrieval
Scoped knowledge packsSource verification before indexingPer-source error reporting
Outbound integrations
Delegated authenticationPer-send job stateConnection health monitoring
Payments
Stripe hosted checkout
Automation
Recipe definitions with parameters, expected outputs, credit cost and run history

More case studies

View all case studies

Building a platform where every action has a cost you need to see?

Tell us what you're building, and we'll tell you honestly how we'd approach it.

Book a discovery call